+/**\r
+\r
+ Validate input console variable data. \r
+\r
+ If found the device path is not a valid device path, remove the variable.\r
+ \r
+ @param VariableName Input console variable name.\r
+\r
+**/\r
+VOID\r
+BdsFormalizeConsoleVariable (\r
+ IN CHAR16 *VariableName\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINTN VariableSize;\r
+ EFI_STATUS Status;\r
+\r
+ DevicePath = BdsLibGetVariableAndSize (\r
+ VariableName,\r
+ &gEfiGlobalVariableGuid,\r
+ &VariableSize\r
+ );\r
+ if ((DevicePath != NULL) && !IsDevicePathValid (DevicePath, VariableSize)) { \r
+ Status = gRT->SetVariable (\r
+ VariableName,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ 0,\r
+ NULL\r
+ );\r
+ //\r
+ // Deleting variable with current variable implementation shouldn't fail.\r
+ //\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Formalize Bds global variables. \r
+\r
+ 1. For ConIn/ConOut/ConErr, if found the device path is not a valid device path, remove the variable.\r
+ 2. For OsIndicationsSupported, Create a BS/RT/UINT64 variable to report caps \r
+ 3. Delete OsIndications variable if it is not NV/BS/RT UINT64\r
+ Item 3 is used to solve case when OS corrupts OsIndications. Here simply delete this NV variable.\r
+ \r
+**/\r
+VOID \r
+BdsFormalizeEfiGlobalVariable (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT64 OsIndicationSupport;\r
+ UINT64 OsIndication;\r
+ UINTN DataSize;\r
+ UINT32 Attributes;\r
+ \r
+ //\r
+ // Validate Console variable.\r
+ //\r
+ BdsFormalizeConsoleVariable (L"ConIn");\r
+ BdsFormalizeConsoleVariable (L"ConOut");\r
+ BdsFormalizeConsoleVariable (L"ErrOut");\r
+\r
+ //\r
+ // OS indicater support variable\r
+ //\r
+ OsIndicationSupport = EFI_OS_INDICATIONS_BOOT_TO_FW_UI \\r
+ | EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED;\r
+\r
+ BdsDxeSetVariableAndReportStatusCodeOnError (\r
+ L"OsIndicationsSupported",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ sizeof(UINT64),\r
+ &OsIndicationSupport\r
+ );\r
+\r
+ //\r
+ // If OsIndications is invalid, remove it.\r
+ // Invalid case\r
+ // 1. Data size != UINT64\r
+ // 2. OsIndication value inconsistence\r
+ // 3. OsIndication attribute inconsistence\r
+ //\r
+ OsIndication = 0;\r
+ Attributes = 0;\r
+ DataSize = sizeof(UINT64);\r
+ Status = gRT->GetVariable (\r
+ L"OsIndications",\r
+ &gEfiGlobalVariableGuid,\r
+ &Attributes,\r
+ &DataSize,\r
+ &OsIndication\r
+ );\r
+\r
+ if (!EFI_ERROR(Status)) {\r
+ if (DataSize != sizeof(UINT64) ||\r
+ (OsIndication & ~OsIndicationSupport) != 0 ||\r
+ Attributes != (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE)){\r
+\r
+ DEBUG ((EFI_D_ERROR, "Unformalized OsIndications variable exists. Delete it\n"));\r
+ Status = gRT->SetVariable (\r
+ L"OsIndications",\r
+ &gEfiGlobalVariableGuid,\r
+ 0,\r
+ 0,\r
+ NULL\r
+ );\r
+ //\r
+ // Deleting variable with current variable implementation shouldn't fail.\r
+ //\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ }\r
+\r
+}\r
+\r
+/**\r
+\r
+ Allocate a block of memory that will contain performance data to OS.\r
+\r
+**/\r
+VOID\r
+BdsAllocateMemoryForPerformanceData (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase;\r
+ EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;\r
+\r
+ AcpiLowMemoryBase = 0x0FFFFFFFFULL;\r
+\r
+ //\r
+ // Allocate a block of memory that will contain performance data to OS.\r
+ //\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiReservedMemoryType,\r
+ EFI_SIZE_TO_PAGES (PERF_DATA_MAX_LENGTH),\r
+ &AcpiLowMemoryBase\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Save the pointer to variable for use in S3 resume.\r
+ //\r
+ BdsDxeSetVariableAndReportStatusCodeOnError (\r
+ L"PerfDataMemAddr",\r
+ &gPerformanceProtocolGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ sizeof (EFI_PHYSICAL_ADDRESS),\r
+ &AcpiLowMemoryBase\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "[Bds] PerfDataMemAddr (%08x) cannot be saved to NV storage.\n", AcpiLowMemoryBase));\r
+ }\r
+ //\r
+ // Mark L"PerfDataMemAddr" variable to read-only if the Variable Lock protocol exists\r
+ // Still lock it even the variable cannot be saved to prevent it's set by 3rd party code.\r
+ //\r
+ Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = VariableLock->RequestToLock (VariableLock, L"PerfDataMemAddr", &gPerformanceProtocolGuid);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ }\r
+}\r
+\r