From 045f4521f2dffa1f788ea12f2952782f3db627de Mon Sep 17 00:00:00 2001 From: davidhuang Date: Thu, 6 Jul 2006 06:42:48 +0000 Subject: 1)Add a new module CapsuleRuntime under EdkModulePkg\Universal\Capsule\RuntimeDxe.And add the module into Nt32.fpd 2)Modify the related files to fit for the runtime services UpdateCapsule/QueryCapsuleCapabilities defined in UEFI2.0 spec 3)Modify the related files to fit for the runtime services QueryVariableInfo defined in UEFI2.0 spec git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@790 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Universal/Capsule/RuntimeDxe/Capsule.c | 68 ++++++ .../Universal/Capsule/RuntimeDxe/Capsule.dxs | 26 +++ .../Capsule/RuntimeDxe/CapsuleRuntime.mbd | 45 ++++ .../Capsule/RuntimeDxe/CapsuleRuntime.msa | 108 ++++++++++ .../Universal/Capsule/RuntimeDxe/CapsuleService.c | 238 +++++++++++++++++++++ .../Universal/Capsule/RuntimeDxe/CapsuleService.h | 47 ++++ .../Universal/Capsule/RuntimeDxe/build.xml | 47 ++++ .../Universal/EmuVariable/RuntimeDxe/EmuVariable.c | 119 +++++++++++ .../EmuVariable/RuntimeDxe/InitVariable.c | 33 +++ .../EmuVariable/RuntimeDxe/Ipf/InitVariable.c | 17 ++ .../Universal/EmuVariable/RuntimeDxe/Variable.h | 14 ++ .../Universal/Runtime/RuntimeDxe/Runtime.c | 20 ++ .../Universal/Variable/RuntimeDxe/InitVariable.c | 33 +++ .../Variable/RuntimeDxe/Ipf/InitVariable.c | 17 ++ .../Universal/Variable/RuntimeDxe/Variable.c | 129 +++++++++++ .../Universal/Variable/RuntimeDxe/Variable.h | 14 ++ 16 files changed, 975 insertions(+) create mode 100644 EdkModulePkg/Universal/Capsule/RuntimeDxe/Capsule.c create mode 100644 EdkModulePkg/Universal/Capsule/RuntimeDxe/Capsule.dxs create mode 100644 EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleRuntime.mbd create mode 100644 EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleRuntime.msa create mode 100644 EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleService.c create mode 100644 EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleService.h create mode 100644 EdkModulePkg/Universal/Capsule/RuntimeDxe/build.xml (limited to 'EdkModulePkg/Universal') diff --git a/EdkModulePkg/Universal/Capsule/RuntimeDxe/Capsule.c b/EdkModulePkg/Universal/Capsule/RuntimeDxe/Capsule.c new file mode 100644 index 0000000..125a445 --- /dev/null +++ b/EdkModulePkg/Universal/Capsule/RuntimeDxe/Capsule.c @@ -0,0 +1,68 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Capsule.c + +Abstract: + + Capsule Runtime Service Initialization + +--*/ + +#include "CapsuleService.h" + + +EFI_STATUS +EFIAPI +CapsuleServiceInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + This code is capsule runtime service initialization. + +Arguments: + + ImageHandle The image handle + SystemTable The system table. + +Returns: + + EFI STATUS + +--*/ +{ + EFI_STATUS Status; + EFI_HANDLE NewHandle; + + SystemTable->RuntimeServices->UpdateCapsule = UpdateCapsule; + SystemTable->RuntimeServices->QueryCapsuleCapabilities = QueryCapsuleCapabilities; + + // + // Now install the Capsule Architectural Protocol on a new handle + // + NewHandle = NULL; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &NewHandle, + &gEfiCapsuleArchProtocolGuid, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/Capsule/RuntimeDxe/Capsule.dxs b/EdkModulePkg/Universal/Capsule/RuntimeDxe/Capsule.dxs new file mode 100644 index 0000000..11da2b9 --- /dev/null +++ b/EdkModulePkg/Universal/Capsule/RuntimeDxe/Capsule.dxs @@ -0,0 +1,26 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Capsule.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include +#include "DxeDepex.h" + +DEPENDENCY_START + EFI_VARIABLE_ARCH_PROTOCOL_GUID +DEPENDENCY_END \ No newline at end of file diff --git a/EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleRuntime.mbd b/EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleRuntime.mbd new file mode 100644 index 0000000..1ae0c53 --- /dev/null +++ b/EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleRuntime.mbd @@ -0,0 +1,45 @@ + + + + + CapsuleRuntime + 42857F0A-13F2-4B21-8A23-53D3F714B840 + 0 + FIX ME! + Copyright (c) 2004-2006, Intel Corporation + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + BaseLib + BaseMemoryLib + UefiDriverEntryPoint + DxeServicesTableLib + EdkDxeRuntimeDriverLib + UefiLib + BaseDebugLibNull + BasePrintLib + DxeMemoryAllocationLib + UefiBootServicesTableLib + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleRuntime.msa b/EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleRuntime.msa new file mode 100644 index 0000000..ea947cc --- /dev/null +++ b/EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleRuntime.msa @@ -0,0 +1,108 @@ + + + + + CapsuleRuntime + DXE_RUNTIME_DRIVER + 42857F0A-13F2-4B21-8A23-53D3F714B840 + 1.0 + Component description file for Capsule module. + FIX ME! + Copyright (c) 2004-2006, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + CapsuleRuntime + + + + BaseLib + + + UefiLib + + + UefiDriverEntryPoint + + + DxeServicesTableLib + + + DxeRuntimeDriverLib + + + DebugLib + + + PcdLib + + + BaseMemoryLib + + + UefiBootServicesTableLib + + + + Capsule.c + CapsuleService.c + CapsuleService.h + Capsule.dxs + + + + + + + + Capsule + + + + + CapsuleVendor + + + Capsule + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00090000 + + CapsuleServiceInitialize + + + + + PcdSupportUpdateCapsuleRest + gEfiEdkModulePkgTokenSpaceGuid + Fix Me! + + + MaxSizePopulateCapsule + gEfiEdkModulePkgTokenSpaceGuid + Fix Me! + + + MaxSizeNonPopulateCapsule + gEfiEdkModulePkgTokenSpaceGuid + Fix Me! + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleService.c b/EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleService.c new file mode 100644 index 0000000..e07cbc8 --- /dev/null +++ b/EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleService.c @@ -0,0 +1,238 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + CapsuleService.c + +Abstract: + + Capsule Runtime Service. + +--*/ + +#include "CapsuleService.h" + + +STATIC EFI_GUID mEfiCapsuleHeaderGuid = EFI_CAPSULE_GUID; + + +EFI_STATUS +EFIAPI +UpdateCapsule ( + IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL + ) +/*++ + +Routine Description: + + This code finds whether the capsules need reset to update, if not, update immediately. + +Arguments: + + CapsuleHeaderArray A array of pointers to capsule headers passed in + CapsuleCount The number of capsule + ScatterGatherList Physical address of datablock list points to capsule + +Returns: + + EFI STATUS + EFI_SUCCESS Valid capsule was passed.If CAPSULE_FLAG_PERSIT_ACROSS_RESET is + not set, the capsule has been successfully processed by the firmware. + If it set, the ScattlerGatherList is successfully to be set. + EFI_INVALID_PARAMETER CapsuleCount is less than 1,CapsuleGuid is not supported. + EFI_DEVICE_ERROR Failed to SetVariable or AllocatePool or ProcessFirmwareVolume. + +--*/ +{ + UINTN CapsuleSize; + UINTN ArrayNumber; + VOID *BufferPtr; + EFI_STATUS Status; + EFI_HANDLE FvHandle; + UEFI_CAPSULE_HEADER *CapsuleHeader; + + if (CapsuleCount < 1) { + return EFI_INVALID_PARAMETER; + } + + BufferPtr = NULL; + CapsuleHeader = NULL; + + // + //Compare GUIDs with EFI_CAPSULE_GUID, if capsule header contains CAPSULE_FLAGS_PERSIST_ACROSS_RESET + //and CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flags,whatever the GUID is ,the service supports. + // + for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) { + CapsuleHeader = CapsuleHeaderArray[ArrayNumber]; + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) && !(CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET)) { + return EFI_INVALID_PARAMETER; + } + if (!CompareGuid (&CapsuleHeader->CapsuleGuid, &mEfiCapsuleHeaderGuid)) { + if (!(CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) { + return EFI_UNSUPPORTED; + } + } + } + + // + //Assume that capsules have the same flags on reseting or not. + // + CapsuleHeader = CapsuleHeaderArray[0]; + + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) { + // + //Check if the platform supports update capsule across a system reset + // + if (!FeaturePcdGet(PcdSupportUpdateCapsuleRest)) { + return EFI_UNSUPPORTED; + } + + if (ScatterGatherList == 0) { + return EFI_INVALID_PARAMETER; + } else { + Status = EfiSetVariable ( + EFI_CAPSULE_VARIABLE_NAME, + &gEfiCapsuleVendorGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (UINTN), + (VOID *) &ScatterGatherList + ); + if (Status != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + } + return EFI_SUCCESS; + } + + // + //The rest occurs in the condition of non-reset mode + // + if (EfiAtRuntime ()) { + return EFI_INVALID_PARAMETER; + } + + // + //Here should be in the boot-time + // + for (ArrayNumber = 0; ArrayNumber < CapsuleCount ; ArrayNumber++) { + CapsuleHeader = CapsuleHeaderArray[ArrayNumber]; + CapsuleSize = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize; + Status = gBS->AllocatePool (EfiBootServicesData, CapsuleSize, &BufferPtr); + if (Status != EFI_SUCCESS) { + goto Done; + } + gBS->CopyMem (BufferPtr, (UINT8*)CapsuleHeader+ CapsuleHeader->HeaderSize, CapsuleSize); + + // + //Call DXE service ProcessFirmwareVolume to process immediatelly + // + Status = gDS->ProcessFirmwareVolume (BufferPtr, CapsuleSize, &FvHandle); + if (Status != EFI_SUCCESS) { + gBS->FreePool (BufferPtr); + return EFI_DEVICE_ERROR; + } + gDS->Dispatch (); + gBS->FreePool (BufferPtr); + } + return EFI_SUCCESS; + +Done: + if (BufferPtr != NULL) { + gBS->FreePool (BufferPtr); + } + return EFI_DEVICE_ERROR; +} + + + +EFI_STATUS +EFIAPI +QueryCapsuleCapabilities ( + IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + OUT UINT64 *MaxiumCapsuleSize, + OUT EFI_RESET_TYPE *ResetType + ) +/*++ + +Routine Description: + + This code is to query about capsule capability. + +Arguments: + + CapsuleHeaderArray A array of pointers to capsule headers passed in + CapsuleCount The number of capsule + MaxiumCapsuleSize Max capsule size is supported + ResetType Reset type the capsule indicates, if reset is not needed,return EfiResetCold. + If reset is needed, return EfiResetWarm. + +Returns: + + EFI STATUS + EFI_SUCCESS Valid answer returned + EFI_INVALID_PARAMETER MaxiumCapsuleSize is NULL,ResetType is NULL.CapsuleCount is less than 1,CapsuleGuid is not supported. + EFI_UNSUPPORTED The capsule type is not supported. + +--*/ +{ + UINTN ArrayNumber; + UEFI_CAPSULE_HEADER *CapsuleHeader; + + if (CapsuleCount < 1) { + return EFI_INVALID_PARAMETER; + } + + if ((MaxiumCapsuleSize == NULL) ||(ResetType == NULL)) { + return EFI_INVALID_PARAMETER; + } + + CapsuleHeader = NULL; + + // + //Compare GUIDs with EFI_CAPSULE_GUID, if capsule header contains CAPSULE_FLAGS_PERSIST_ACROSS_RESET + //and CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flags,whatever the GUID is ,the service supports. + // + for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) { + CapsuleHeader = CapsuleHeaderArray[ArrayNumber]; + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) && !(CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET)) { + return EFI_INVALID_PARAMETER; + } + if (!CompareGuid (&CapsuleHeader->CapsuleGuid, &mEfiCapsuleHeaderGuid)) { + if (!(CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) { + return EFI_UNSUPPORTED; + } + } + } + + // + //Assume that capsules have the same flags on reseting or not. + // + CapsuleHeader = CapsuleHeaderArray[0]; + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) { + // + //Check if the platform supports update capsule across a system reset + // + if (!FeaturePcdGet(PcdSupportUpdateCapsuleRest)) { + return EFI_UNSUPPORTED; + } + *ResetType = EfiResetWarm; + *MaxiumCapsuleSize = FixedPcdGet32(PcdMaxSizePopulateCapsule); + } else { + *ResetType = EfiResetCold; + *MaxiumCapsuleSize = FixedPcdGet32(PcdMaxSizeNonPopulateCapsule); + } + return EFI_SUCCESS; +} + diff --git a/EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleService.h b/EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleService.h new file mode 100644 index 0000000..c5ff6c7 --- /dev/null +++ b/EdkModulePkg/Universal/Capsule/RuntimeDxe/CapsuleService.h @@ -0,0 +1,47 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + CapsuleService.h + +Abstract: + + Capsule Runtime Service + +--*/ + +#ifndef _CAPSULE_RUNTIME_H_ +#define _CAPSULE_RUNTIME_H_ + +#include + + + +EFI_STATUS +EFIAPI +UpdateCapsule( + IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL + ); + +EFI_STATUS +EFIAPI +QueryCapsuleCapabilities( + IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + OUT UINT64 *MaxiumCapsuleSize, + OUT EFI_RESET_TYPE *ResetType + ); + +#endif + diff --git a/EdkModulePkg/Universal/Capsule/RuntimeDxe/build.xml b/EdkModulePkg/Universal/Capsule/RuntimeDxe/build.xml new file mode 100644 index 0000000..d376719 --- /dev/null +++ b/EdkModulePkg/Universal/Capsule/RuntimeDxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.c b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.c index beb404f..6614bb0 100644 --- a/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.c +++ b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.c @@ -656,6 +656,125 @@ 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 (Variable < GetEndPointer (VariableStoreHeader)) { + if (Variable->StartId != VARIABLE_DATA) { + break; + } + + NextVariable = (VARIABLE_HEADER *) (GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize)); + VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable; + + if (Variable->State == VAR_ADDED) { + *RemainingVariableStorageSize -= VariableSize; + } + + // + // Go to the next one. + // + Variable = NextVariable; + } + + return EFI_SUCCESS; +} +#endif + EFI_STATUS EFIAPI InitializeVariableStore ( diff --git a/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/InitVariable.c b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/InitVariable.c index 0ad8664..477869c 100644 --- a/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/InitVariable.c +++ b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/InitVariable.c @@ -114,6 +114,36 @@ Returns: ); } +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) +EFI_STATUS +EFIAPI +RuntimeServiceQueryVariableInfo ( + IN UINT32 Attributes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + return QueryVariableInfo ( + Attributes, + MaximumVariableStorageSize, + RemainingVariableStorageSize, + MaximumVariableSize, + &mVariableModuleGlobal->VariableBase[Physical], + mVariableModuleGlobal->FvbInstance + ); +} +#endif + VOID EFIAPI VariableClassAddressChangeEvent ( @@ -166,6 +196,9 @@ Returns: SystemTable->RuntimeServices->GetVariable = RuntimeServiceGetVariable; SystemTable->RuntimeServices->GetNextVariableName = RuntimeServiceGetNextVariableName; SystemTable->RuntimeServices->SetVariable = RuntimeServiceSetVariable; +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + SystemTable->RuntimeServices->QueryVariableInfo = RuntimeServiceQueryVariableInfo; +#endif // // Now install the Variable Runtime Architectural Protocol on a new handle diff --git a/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/Ipf/InitVariable.c b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/Ipf/InitVariable.c index 061e6db..ee2a485 100644 --- a/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/Ipf/InitVariable.c +++ b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/Ipf/InitVariable.c @@ -89,6 +89,19 @@ Returns: ); return ReturnVal; +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + case EsalQueryVariableInfo: + ReturnVal.Status = QueryVariableInfo ( + (UINT32) Arg2, + (UINT64 *) Arg3, + (UINT64 *) Arg4, + (UINT64 *) Arg5, + &Global->VariableBase[VirtualMode], + Global->FvbInstance + ); + return ReturnVal; +#endif + default: ReturnVal.Status = EFI_SAL_INVALID_ARGUMENT; return ReturnVal; @@ -160,6 +173,10 @@ Returns: EsalGetNextVariableName, EsalVariableCommonEntry, EsalSetVariable, +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + EsalVariableCommonEntry, + EsalQueryVariableInfo, +#endif NULL ); diff --git a/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/Variable.h b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/Variable.h index d1fd5e2..55423a2 100644 --- a/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/Variable.h +++ b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/Variable.h @@ -140,4 +140,18 @@ SetVariable ( ) ; +#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 + ) +; +#endif + #endif diff --git a/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.c b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.c index 5a21d49..d2428ea 100644 --- a/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.c +++ b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.c @@ -92,6 +92,9 @@ UINTN mVirtualMapMaxIndex; EFI_LOADED_IMAGE_PROTOCOL *mMyLoadedImage; +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) +STATIC EFI_GUID mEfiCapsuleHeaderGuid = EFI_CAPSULE_GUID; +#endif // // Worker Functions // @@ -356,6 +359,9 @@ RuntimeDriverSetVirtualAddressMap ( UINTN Index1; EFI_DRIVER_OS_HANDOFF_HEADER *DriverOsHandoffHeader; EFI_DRIVER_OS_HANDOFF *DriverOsHandoff; +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + EFI_CAPSULE_TABLE *CapsuleTable; +#endif // // Can only switch to virtual addresses once the memory map is locked down, @@ -464,6 +470,11 @@ RuntimeDriverSetVirtualAddressMap ( RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetVariable); RuntimeDriverConvertInternalPointer ((VOID **) &gRT->SetVariable); RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetNextVariableName); +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + RuntimeDriverConvertInternalPointer ((VOID **) &gRT->QueryVariableInfo); + RuntimeDriverConvertInternalPointer ((VOID **) &gRT->UpdateCapsule); + RuntimeDriverConvertInternalPointer ((VOID **) &gRT->QueryCapsuleCapabilities); +#endif RuntimeDriverCalculateEfiHdrCrc (&gRT->Hdr); // @@ -486,6 +497,15 @@ RuntimeDriverSetVirtualAddressMap ( RuntimeDriverConvertPointer (EFI_OPTIONAL_POINTER, (VOID **) &(gST->ConfigurationTable[Index].VendorTable)); } +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + if (CompareGuid (&mEfiCapsuleHeaderGuid, &(gST->ConfigurationTable[Index].VendorGuid))) { + CapsuleTable = gST->ConfigurationTable[Index].VendorTable; + for (Index1 = 0; Index1 < CapsuleTable->CapsuleArrayNumber; Index1++) { + RuntimeDriverConvertPointer (EFI_OPTIONAL_POINTER, (VOID **) &CapsuleTable->CapsulePtr[Index1]); + } + RuntimeDriverConvertPointer (EFI_OPTIONAL_POINTER, (VOID **) &(gST->ConfigurationTable[Index].VendorTable)); + } +#endif } // // Convert the runtime fields of the EFI System Table and recompute the CRC-32 diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/InitVariable.c b/EdkModulePkg/Universal/Variable/RuntimeDxe/InitVariable.c index 0ad8664..477869c 100644 --- a/EdkModulePkg/Universal/Variable/RuntimeDxe/InitVariable.c +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/InitVariable.c @@ -114,6 +114,36 @@ Returns: ); } +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) +EFI_STATUS +EFIAPI +RuntimeServiceQueryVariableInfo ( + IN UINT32 Attributes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + return QueryVariableInfo ( + Attributes, + MaximumVariableStorageSize, + RemainingVariableStorageSize, + MaximumVariableSize, + &mVariableModuleGlobal->VariableBase[Physical], + mVariableModuleGlobal->FvbInstance + ); +} +#endif + VOID EFIAPI VariableClassAddressChangeEvent ( @@ -166,6 +196,9 @@ Returns: SystemTable->RuntimeServices->GetVariable = RuntimeServiceGetVariable; SystemTable->RuntimeServices->GetNextVariableName = RuntimeServiceGetNextVariableName; SystemTable->RuntimeServices->SetVariable = RuntimeServiceSetVariable; +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + SystemTable->RuntimeServices->QueryVariableInfo = RuntimeServiceQueryVariableInfo; +#endif // // Now install the Variable Runtime Architectural Protocol on a new handle diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/Ipf/InitVariable.c b/EdkModulePkg/Universal/Variable/RuntimeDxe/Ipf/InitVariable.c index 061e6db..ee2a485 100644 --- a/EdkModulePkg/Universal/Variable/RuntimeDxe/Ipf/InitVariable.c +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/Ipf/InitVariable.c @@ -89,6 +89,19 @@ Returns: ); return ReturnVal; +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + case EsalQueryVariableInfo: + ReturnVal.Status = QueryVariableInfo ( + (UINT32) Arg2, + (UINT64 *) Arg3, + (UINT64 *) Arg4, + (UINT64 *) Arg5, + &Global->VariableBase[VirtualMode], + Global->FvbInstance + ); + return ReturnVal; +#endif + default: ReturnVal.Status = EFI_SAL_INVALID_ARGUMENT; return ReturnVal; @@ -160,6 +173,10 @@ Returns: EsalGetNextVariableName, EsalVariableCommonEntry, EsalSetVariable, +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + EsalVariableCommonEntry, + EsalQueryVariableInfo, +#endif NULL ); diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.c b/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.c index 0d91520..cfd3183 100644 --- a/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.c +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.c @@ -1090,6 +1090,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 ( diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.h b/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.h index d1fd5e2..55423a2 100644 --- a/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.h +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.h @@ -140,4 +140,18 @@ SetVariable ( ) ; +#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 + ) +; +#endif + #endif -- cgit v1.1