gEfiCapsuleVendorGuid = { 0x711C703F, 0xC285, 0x4B10, { 0xA3, 0xB0, 0x36, 0xEC, 0xBD, 0x3C, 0x8B, 0xE2 }}\r
gPeiPerformanceHobGuid = { 0xEC4DF5AF, 0x4395, 0x4CC9, { 0x94, 0xDE, 0x77, 0x50, 0x6D, 0x12, 0xC7, 0xB8 }}\r
gEfiGenericPlatformVariableGuid = { 0x59d1c24f, 0x50f1, 0x401a, { 0xb1, 0x01, 0xf3, 0x3e, 0x0d, 0xae, 0xd4, 0x43 }}\r
-\r
gEfiShellFileGuid = { 0xC57AD6B7, 0x0515, 0x40A8, { 0x9D, 0x21, 0x55, 0x16, 0x52, 0x85, 0x4E, 0x37 }}\r
gEfiFlashMapHobGuid = { 0xB091E7D2, 0x05A0, 0x4198, { 0x94, 0xF0, 0x74, 0xB7, 0xB8, 0xC5, 0x54, 0x59 }}\r
gEfiStandardErrorDeviceGuid = { 0xD3B36F2D, 0xD551, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}\r
-\r
gEfiPeiPeCoffLoaderGuid = { 0xD8117CFF, 0x94A6, 0x11D4, { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}\r
+ gEfiVariableInfoGuid = { 0xddcf3616, 0x3275, 0x4164, { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d }}\r
\r
[Protocols.common]\r
\r
gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathFromText|FALSE|BOOLEAN|0x00010038\r
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildShareCodeHobs|FALSE|BOOLEAN|0x0001003c\r
gEfiMdeModulePkgTokenSpaceGuid.PcdNtEmulatorEnable|FALSE|BOOLEAN|0x0001003e\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics|FALSE|BOOLEAN|0x0001003f\r
\r
[PcdsFixedAtBuild.common]\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPcdCallBackNumberPerPcdEntry|0x08|UINT32|0x0001000f\r
--- /dev/null
+/** @file\r
+ If the Variable services have PcdVariableCollectStatistics set to TRUE then \r
+ the EFI system table will contain statistical information about variable usage\r
+ an this utility will print out the information. You can use console redirection\r
+ to capture the data.\r
+ \r
+ Copyright (c) 2006 - 2007, Intel Corporation \r
+ All rights reserved. This program and the accompanying materials \r
+ are licensed and made available under the terms and conditions of the BSD License \r
+ which accompanies this distribution. The full text of the license may be found at \r
+ http://opensource.org/licenses/bsd-license.php \r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+**/\r
+\r
+#include <Uefi.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/UefiApplicationEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Guid/VariableInfo.h>\r
+\r
+\r
+/**\r
+ The user Entry Point for Application. The user code starts with this function\r
+ as the real entry point for the image goes into a library that calls this \r
+ function.\r
+\r
+\r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
+ @param[in] SystemTable A pointer to the EFI System Table.\r
+ \r
+ @retval EFI_SUCCESS The entry point is executed successfully.\r
+ @retval other Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UefiMain (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VARIABLE_INFO_ENTRY *VariableInfo;\r
+ VARIABLE_INFO_ENTRY *Entry;\r
+\r
+ Status = EfiGetSystemConfigurationTable (&gEfiVariableInfoGuid, (VOID **)&Entry);\r
+ if (!EFI_ERROR (Status) && (Entry != NULL)) {\r
+ Print (L"Non-Volatile EFI Variables:\n");\r
+ VariableInfo = Entry;\r
+ do {\r
+ if (!VariableInfo->Volatile) {\r
+ Print (\r
+ L"%g R%03d(%03d) W%03d D%03d:%s\n", \r
+ &VariableInfo->VendorGuid, \r
+ VariableInfo->ReadCount,\r
+ VariableInfo->CacheCount,\r
+ VariableInfo->WriteCount,\r
+ VariableInfo->DeleteCount,\r
+ VariableInfo->Name\r
+ );\r
+ }\r
+\r
+ VariableInfo = VariableInfo->Next;\r
+ } while (VariableInfo != NULL);\r
+\r
+ Print (L"Volatile EFI Variables:\n");\r
+ VariableInfo = Entry;\r
+ do {\r
+ if (VariableInfo->Volatile) {\r
+ Print (\r
+ L"%g R%03d(%03d) W%03d D%03d:%s\n", \r
+ &VariableInfo->VendorGuid, \r
+ VariableInfo->ReadCount,\r
+ VariableInfo->CacheCount,\r
+ VariableInfo->WriteCount,\r
+ VariableInfo->DeleteCount,\r
+ VariableInfo->Name\r
+ );\r
+ }\r
+ VariableInfo = VariableInfo->Next;\r
+ } while (VariableInfo != NULL);\r
+\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
\r
#include "Variable.h"\r
#include <Guid/FlashMapHob.h>\r
+#include <Guid/VariableInfo.h>\r
+#include <Guid/GlobalVariable.h>\r
+\r
+\r
+\r
\r
//\r
// Don't use module globals after the SetVirtualAddress map is signaled\r
//\r
ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal;\r
\r
+\r
//\r
// This is a temperary function which will be removed\r
// when EfiAcquireLock in UefiLib can handle the\r
// the call in UEFI Runtimer driver in RT phase.\r
//\r
-STATIC\r
VOID\r
AcquireLockOnlyAtBootTime (\r
IN EFI_LOCK *Lock\r
// when EfiAcquireLock in UefiLib can handle the\r
// the call in UEFI Runtimer driver in RT phase.\r
//\r
-STATIC\r
VOID\r
ReleaseLockOnlyAtBootTime (\r
IN EFI_LOCK *Lock\r
}\r
}\r
\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED VARIABLE_INFO_ENTRY *gVariableInfo = NULL;\r
+\r
+\r
+VOID\r
+UpdateVariableInfo (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ IN BOOLEAN Volatile,\r
+ IN BOOLEAN Read,\r
+ IN BOOLEAN Write,\r
+ IN BOOLEAN Delete,\r
+ IN BOOLEAN Cache\r
+ )\r
+{\r
+ VARIABLE_INFO_ENTRY *Entry;\r
+\r
+ if (FeaturePcdGet (PcdVariableCollectStatistics)) {\r
+\r
+ if (EfiAtRuntime ()) {\r
+ // Don't collect statistics at runtime\r
+ return;\r
+ }\r
+\r
+ if (gVariableInfo == NULL) {\r
+ gVariableInfo = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));\r
+ CopyGuid (&gVariableInfo->VendorGuid, VendorGuid);\r
+ gVariableInfo->Name = AllocatePool (StrLen (VariableName));\r
+ StrCpy (gVariableInfo->Name, VariableName);\r
+ gVariableInfo->Volatile = Volatile;\r
+\r
+ gBS->InstallConfigurationTable (&gEfiVariableInfoGuid, gVariableInfo);\r
+ }\r
+\r
+ \r
+ for (Entry = gVariableInfo; Entry != NULL; Entry = Entry->Next) {\r
+ if (CompareGuid (VendorGuid, &Entry->VendorGuid)) {\r
+ if (StrCmp (VariableName, Entry->Name) == 0) {\r
+ if (Read) {\r
+ Entry->ReadCount++;\r
+ }\r
+ if (Write) {\r
+ Entry->WriteCount++;\r
+ }\r
+ if (Delete) {\r
+ Entry->DeleteCount++;\r
+ }\r
+ if (Cache) {\r
+ Entry->CacheCount++;\r
+ }\r
+\r
+ return;\r
+ }\r
+ }\r
+\r
+ if (Entry->Next == NULL) {\r
+ Entry->Next = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));\r
+\r
+ CopyGuid (&Entry->Next->VendorGuid, VendorGuid);\r
+ Entry->Next->Name = AllocatePool (StrLen (VariableName));\r
+ StrCpy (Entry->Next->Name, VariableName);\r
+ Entry->Next->Volatile = Volatile;\r
+ }\r
+\r
+ }\r
+ }\r
+}\r
+\r
+\r
+\r
STATIC\r
BOOLEAN\r
EFIAPI\r
return Status;\r
}\r
\r
-STATIC\r
+typedef struct {\r
+ EFI_GUID *Guid;\r
+ CHAR16 *Name;\r
+ UINT32 Attributes;\r
+ UINTN DataSize;\r
+ VOID *Data;\r
+} VARIABLE_CACHE_ENTRY;\r
+\r
+//\r
+// The current Hii implementation accesses this variable a larg # of times on every boot.\r
+// Other common variables are only accessed a single time. This is why this cache algorithm\r
+// only targets a single variable. Probably to get an performance improvement out of\r
+// a Cache you would need a cache that improves the search performance for a variable.\r
+//\r
+VARIABLE_CACHE_ENTRY mVariableCache[] = {\r
+ {\r
+ &gEfiGlobalVariableGuid,\r
+ L"Lang",\r
+ 0x00000000,\r
+ 0x00,\r
+ NULL\r
+ }\r
+};\r
+\r
+VOID\r
+UpdateVariableCache (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ OUT UINT32 Attributes,\r
+ IN OUT UINTN DataSize,\r
+ OUT VOID *Data\r
+ )\r
+{\r
+ VARIABLE_CACHE_ENTRY *Entry;\r
+ UINTN Index;\r
+\r
+ if (EfiAtRuntime ()) {\r
+ // Don't use the cache at runtime\r
+ return;\r
+ }\r
+\r
+ for (Index = 0, Entry = mVariableCache; Index < sizeof (mVariableCache)/sizeof (VARIABLE_CACHE_ENTRY); Index++, Entry++) {\r
+ if (CompareGuid (VendorGuid, Entry->Guid)) {\r
+ if (StrCmp (VariableName, Entry->Name) == 0) { \r
+ Entry->Attributes = Attributes;\r
+ if (DataSize == 0) {\r
+ // Delete Case\r
+ if (Entry->DataSize != 0) {\r
+ FreePool (Entry->Data);\r
+ }\r
+ Entry->DataSize = DataSize;\r
+ } else if (DataSize == Entry->DataSize) {\r
+ CopyMem (Entry->Data, Data, DataSize);\r
+ } else {\r
+ Entry->Data = AllocatePool (DataSize);\r
+ Entry->DataSize = DataSize;\r
+ CopyMem (Entry->Data, Data, DataSize);\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+\r
+EFI_STATUS\r
+FindVariableInCache (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ OUT UINT32 *Attributes OPTIONAL,\r
+ IN OUT UINTN *DataSize,\r
+ OUT VOID *Data\r
+ )\r
+{\r
+ VARIABLE_CACHE_ENTRY *Entry;\r
+ UINTN Index;\r
+\r
+ if (EfiAtRuntime ()) {\r
+ // Don't use the cache at runtime\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ for (Index = 0, Entry = mVariableCache; Index < sizeof (mVariableCache)/sizeof (VARIABLE_CACHE_ENTRY); Index++, Entry++) {\r
+ if (CompareGuid (VendorGuid, Entry->Guid)) {\r
+ if (StrCmp (VariableName, Entry->Name) == 0) {\r
+ if (Entry->DataSize == 0) {\r
+ return EFI_NOT_FOUND;\r
+ } else if (Entry->DataSize != *DataSize) {\r
+ *DataSize = Entry->DataSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ } else {\r
+ CopyMem (Data, Entry->Data, Entry->DataSize);\r
+ if (Attributes != NULL) {\r
+ *Attributes = Entry->Attributes;\r
+ }\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
EFI_STATUS\r
-EFIAPI\r
FindVariable (\r
IN CHAR16 *VariableName,\r
IN EFI_GUID *VendorGuid,\r
AcquireLockOnlyAtBootTime(&Global->VariableServicesLock);\r
\r
//\r
- // 0: Non-Volatile, 1: Volatile\r
+ // 0: Volatile, 1: Non-Volatile\r
//\r
- VariableStoreHeader[0] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);\r
- VariableStoreHeader[1] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);\r
+ VariableStoreHeader[0] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);\r
+ VariableStoreHeader[1] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase);\r
\r
//\r
// Start Pointers for the variable.\r
return EFI_INVALID_PARAMETER;\r
}\r
//\r
- // Find the variable by walk through non-volatile and volatile variable store\r
+ // Find the variable by walk through volatile and then non-volatile variable store\r
//\r
for (Index = 0; Index < 2; Index++) {\r
PtrTrack->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader[Index] + 1);\r
if (!EfiAtRuntime () || (Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {\r
if (VariableName[0] == 0) {\r
PtrTrack->CurrPtr = Variable[Index];\r
- PtrTrack->Volatile = (BOOLEAN) Index;\r
+ PtrTrack->Volatile = (BOOLEAN)(Index == 0);\r
return EFI_SUCCESS;\r
} else {\r
if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) {\r
if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), Variable[Index]->NameSize)) {\r
PtrTrack->CurrPtr = Variable[Index];\r
- PtrTrack->Volatile = (BOOLEAN) Index;\r
+ PtrTrack->Volatile = (BOOLEAN)(Index == 0);\r
return EFI_SUCCESS;\r
}\r
}\r
\r
Variable[Index] = GetNextVariablePtr (Variable[Index]);\r
}\r
- //\r
- // While (...)\r
- //\r
}\r
- //\r
- // for (...)\r
- //\r
PtrTrack->CurrPtr = NULL;\r
return EFI_NOT_FOUND;\r
}\r
\r
+\r
EFI_STATUS\r
EFIAPI\r
GetVariable (\r
if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
+\r
//\r
// Find existing variable\r
//\r
+ Status = FindVariableInCache (VariableName, VendorGuid, Attributes, DataSize, Data);\r
+ if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_SUCCESS)){\r
+ // Hit in the Cache\r
+ UpdateVariableInfo (VariableName, VendorGuid, FALSE, TRUE, FALSE, FALSE, TRUE);\r
+ return Status;\r
+ }\r
+ \r
Status = FindVariable (VariableName, VendorGuid, &Variable, Global);\r
-\r
if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
goto Done;\r
}\r
+\r
//\r
// Get data size\r
//\r
}\r
\r
*DataSize = VarDataSize;\r
+ UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, TRUE, FALSE, FALSE, FALSE);\r
+ UpdateVariableCache (VariableName, VendorGuid, Variable.CurrPtr->Attributes, VarDataSize, Data);\r
+ \r
Status = EFI_SUCCESS;\r
goto Done;\r
} else {\r
sizeof (UINT8),\r
&State\r
); \r
+ if (!EFI_ERROR (Status)) {\r
+ UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, FALSE, FALSE, TRUE, FALSE);\r
+ UpdateVariableCache (VariableName, VendorGuid, Attributes, DataSize, Data);\r
+ }\r
goto Done; \r
}\r
//\r
//\r
if (Variable.CurrPtr->DataSize == DataSize &&\r
(CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize) == 0)) {\r
+ \r
+ UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, FALSE, TRUE, FALSE, FALSE);\r
Status = EFI_SUCCESS;\r
goto Done;\r
} else if ((Variable.CurrPtr->State == VAR_ADDED) ||\r
); \r
if (EFI_ERROR (Status)) {\r
goto Done; \r
- }\r
+ } \r
} \r
} else if (Status == EFI_NOT_FOUND) {\r
//\r
//\r
// Create a nonvolatile variable\r
//\r
+ Variable.Volatile = FALSE;\r
\r
if ((UINT32) (VarSize +*NonVolatileOffset) >\r
((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size\r
//\r
// Create a volatile variable\r
// \r
+ Variable.Volatile = TRUE;\r
\r
if ((UINT32) (VarSize +*VolatileOffset) >\r
((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size) {\r
sizeof (UINT8),\r
&State\r
);\r
+ \r
+ if (!EFI_ERROR (Status)) {\r
+ UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, FALSE, TRUE, FALSE, FALSE);\r
+ UpdateVariableCache (VariableName, VendorGuid, Attributes, DataSize, Data);\r
+ }\r
goto Done; \r
}\r
\r
Status = EFI_SUCCESS;\r
+ UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, FALSE, TRUE, FALSE, FALSE);\r
+ UpdateVariableCache (VariableName, VendorGuid, Attributes, DataSize, Data);\r
+\r
Done:\r
ReleaseLockOnlyAtBootTime (&Global->VariableServicesLock);\r
return Status;\r