\r
CHAR16 mFirmwareVendor[] = L"TianoCore.org";\r
\r
+EFI_EVENT mReadyToBootEvent;\r
+\r
+EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {\r
+ { EfiACPIReclaimMemory, 0 },\r
+ { EfiACPIMemoryNVS, 0 },\r
+ { EfiReservedMemoryType, 0 },\r
+ { EfiRuntimeServicesData, 0 },\r
+ { EfiRuntimeServicesCode, 0 },\r
+ { EfiBootServicesCode, 0 },\r
+ { EfiBootServicesData, 0 },\r
+ { EfiLoaderCode, 0 },\r
+ { EfiLoaderData, 0 },\r
+ { EfiMaxMemoryType, 0 }\r
+};\r
+\r
+VOID \r
+BdsSetMemoryTypeInformationVariable (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_MEMORY_TYPE_INFORMATION *PreviousMemoryTypeInformation;\r
+ EFI_MEMORY_TYPE_INFORMATION *CurrentMemoryTypeInformation;\r
+ UINTN VariableSize;\r
+ BOOLEAN UpdateRequired;\r
+ UINTN Index;\r
+ UINTN Index1;\r
+ UINT32 Previous;\r
+ UINT32 Current;\r
+ UINT32 Next;\r
+ EFI_HOB_GUID_TYPE *Hob;\r
+\r
+ UpdateRequired = FALSE;\r
+\r
+ //\r
+ // Retrieve the current memory usage statistics. If they are not found, then\r
+ // no adjustments can be made to the Memory Type Information variable.\r
+ //\r
+ Status = EfiGetSystemConfigurationTable (&gEfiMemoryTypeInformationGuid, (VOID **)&CurrentMemoryTypeInformation);\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Get the Memory Type Information settings from a previous boot if they exist.\r
+ //\r
+ PreviousMemoryTypeInformation = BdsLibGetVariableAndSize (\r
+ EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,\r
+ &gEfiMemoryTypeInformationGuid,\r
+ &VariableSize\r
+ );\r
+\r
+ //\r
+ // If the previous Memory Type Information is not available, then set defaults\r
+ //\r
+ if (PreviousMemoryTypeInformation == NULL) {\r
+ Hob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);\r
+\r
+ if (Hob != NULL) {\r
+ PreviousMemoryTypeInformation = GET_GUID_HOB_DATA (Hob);\r
+ VariableSize = GET_GUID_HOB_DATA_SIZE (Hob);\r
+ ASSERT (VariableSize == sizeof (mDefaultMemoryTypeInformation));\r
+ CopyMem (mDefaultMemoryTypeInformation, PreviousMemoryTypeInformation, VariableSize);\r
+ } else {\r
+ PreviousMemoryTypeInformation = mDefaultMemoryTypeInformation;\r
+ VariableSize = sizeof (mDefaultMemoryTypeInformation);\r
+ }\r
+ UpdateRequired = TRUE;\r
+ }\r
+\r
+ //\r
+ // Use a hueristic to adjust the Memory Type Information for the next boot\r
+ //\r
+ for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {\r
+\r
+ Current = 0;\r
+ for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) {\r
+ if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) {\r
+ Current = CurrentMemoryTypeInformation[Index1].NumberOfPages;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) {\r
+ continue;\r
+ }\r
+\r
+ Previous = PreviousMemoryTypeInformation[Index].NumberOfPages;\r
+\r
+ if (Current > Previous) {\r
+ Next = Current + (Current >> 2);\r
+ } else if (Current < (Previous >> 1)) {\r
+ Next = Previous - (Previous >> 2);\r
+ } else {\r
+ Next = Previous;\r
+ }\r
+ if (Next > 0 && Next <= 16) {\r
+ Next = 16;\r
+ }\r
+\r
+ if (Next != Previous) {\r
+ PreviousMemoryTypeInformation[Index].NumberOfPages = Next;\r
+ UpdateRequired = TRUE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // If any changes were made to the Memory Type Information settings, then set the new variable value\r
+ //\r
+ if (UpdateRequired) {\r
+ Status = gRT->SetVariable (\r
+ EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,\r
+ &gEfiMemoryTypeInformationGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ VariableSize,\r
+ PreviousMemoryTypeInformation\r
+ );\r
+ }\r
+\r
+ return;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This routine is a notification function for legayc boot or exit boot\r
+ service event. It will adjust the memory information for different\r
+ memory type and save them into the variables for next boot\r
+\r
+Arguments:\r
+\r
+ Event - The event that triggered this notification function\r
+ Context - Pointer to the notification functions context\r
+\r
+Returns:\r
+\r
+ None.\r
+\r
+--*/\r
+VOID\r
+EFIAPI\r
+BdsReadyToBootEvent (\r
+ EFI_EVENT Event,\r
+ VOID *Context\r
+ )\r
+{\r
+ BdsSetMemoryTypeInformationVariable ();\r
+}\r
+\r
//\r
// BDS Platform Functions\r
//\r
//\r
gBS->CalculateCrc32 ((VOID *) gST, sizeof (EFI_SYSTEM_TABLE), &gST->Hdr.CRC32);\r
\r
+ //\r
+ // Create Ready To Boot event\r
+ // \r
+ EfiCreateEventReadyToBootEx (\r
+ TPL_CALLBACK,\r
+ BdsReadyToBootEvent,\r
+ NULL,\r
+ &mReadyToBootEvent\r
+ );\r
+\r
//\r
// Initialize the platform specific string and language\r
//\r