//\r
Status = gBS->LoadImage (\r
FALSE,\r
- mBdsImageHandle,\r
+ gImageHandle,\r
Option->DevicePath,\r
NULL,\r
0,\r
// Unicode stream to ASCII without any loss in meaning.\r
//\r
if (*VariableName == 'B') {\r
- NumOff = sizeof (L"Boot")/sizeof(CHAR16) -1 ;\r
+ NumOff = (UINT8) (sizeof (L"Boot") / sizeof(CHAR16) - 1);\r
Option->BootCurrent = (UINT16) ((VariableName[NumOff] -'0') * 0x1000);\r
Option->BootCurrent = (UINT16) (Option->BootCurrent + ((VariableName[NumOff+1]-'0') * 0x100));\r
Option->BootCurrent = (UINT16) (Option->BootCurrent + ((VariableName[NumOff+2]-'0') * 0x10));\r
//\r
// If the user hits the YES Response key, reset\r
//\r
- if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
}\r
gST->ConOut->ClearScreen (gST->ConOut);\r
}\r
\r
/**\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
-\r
- @param Event The event that triggered this notification function.\r
- @param Context Pointer to the notification functions context.\r
-\r
+ This routine adjust the memory information for different memory type and \r
+ save them into the variables for next boot.\r
**/\r
VOID\r
-EFIAPI\r
BdsSetMemoryTypeInformationVariable (\r
- EFI_EVENT Event,\r
- VOID *Context\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 *GuidHob;\r
+ BOOLEAN MemoryTypeInformationModified;\r
+ BOOLEAN MemoryTypeInformationVariableExists;\r
+ EFI_BOOT_MODE BootMode;\r
+\r
+ MemoryTypeInformationModified = FALSE;\r
+ MemoryTypeInformationVariableExists = FALSE;\r
+\r
\r
- UpdateRequired = FALSE;\r
+ BootMode = GetBootModeHob ();\r
+ //\r
+ // In BOOT_IN_RECOVERY_MODE, Variable region is not reliable.\r
+ //\r
+ if (BootMode == BOOT_IN_RECOVERY_MODE) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Only get the the Memory Type Information variable in the boot mode \r
+ // other than BOOT_WITH_DEFAULT_SETTINGS because the Memory Type\r
+ // Information is not valid in this boot mode.\r
+ //\r
+ if (BootMode != BOOT_WITH_DEFAULT_SETTINGS) {\r
+ VariableSize = 0;\r
+ Status = gRT->GetVariable (\r
+ EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,\r
+ &gEfiMemoryTypeInformationGuid,\r
+ NULL, \r
+ &VariableSize, \r
+ NULL\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ MemoryTypeInformationVariableExists = TRUE;\r
+ }\r
+ }\r
\r
//\r
// Retrieve the current memory usage statistics. If they are not found, then\r
//\r
// Use a heuristic to adjust the Memory Type Information for the next boot\r
//\r
+ DEBUG ((EFI_D_INFO, "Memory Previous Current Next \n"));\r
+ DEBUG ((EFI_D_INFO, " Type Pages Pages Pages \n"));\r
+ DEBUG ((EFI_D_INFO, "====== ======== ======== ========\n"));\r
+\r
for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {\r
\r
Current = 0;\r
//\r
// Write next varible to 125% * current and Inconsistent Memory Reserved across bootings may lead to S4 fail\r
//\r
- if (Current > Previous) {\r
+ if (!MemoryTypeInformationVariableExists && Current < Previous) {\r
+ Next = Current + (Current >> 2);\r
+ } else if (Current > Previous) {\r
Next = Current + (Current >> 2);\r
} else {\r
Next = Previous;\r
\r
if (Next != Previous) {\r
PreviousMemoryTypeInformation[Index].NumberOfPages = Next;\r
- UpdateRequired = TRUE;\r
+ MemoryTypeInformationModified = TRUE;\r
}\r
\r
+ DEBUG ((EFI_D_INFO, " %02x %08x %08x %08x\n", PreviousMemoryTypeInformation[Index].Type, Previous, Current, Next));\r
}\r
\r
//\r
- // If any changes were made to the Memory Type Information settings, then set the new variable value\r
+ // If any changes were made to the Memory Type Information settings, then set the new variable value;\r
+ // Or create the variable in first boot.\r
//\r
- if (UpdateRequired) {\r
+ if (MemoryTypeInformationModified || !MemoryTypeInformationVariableExists) {\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
+ 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
- return;\r
+ //\r
+ // If the Memory Type Information settings have been modified, then reset the platform\r
+ // so the new Memory Type Information setting will be used to guarantee that an S4\r
+ // entry/resume cycle will not fail.\r
+ //\r
+ if (MemoryTypeInformationModified && PcdGetBool (PcdResetOnMemoryTypeInformationChange)) {\r
+ DEBUG ((EFI_D_INFO, "Memory Type Information settings change. Warm Reset!!!\n"));\r
+ gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
+ }\r
+ }\r
}\r
\r
/**\r
- This routine register a function to adjust the different type memory page number\r
- just before booting and save the updated info into the variable for next boot to use.\r
-\r
+ This routine is kept for backward compatibility.\r
**/\r
VOID\r
EFIAPI\r
VOID\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_EVENT ReadyToBootEvent;\r
-\r
- Status = EfiCreateEventReadyToBootEx (\r
- TPL_CALLBACK,\r
- BdsSetMemoryTypeInformationVariable,\r
- NULL,\r
- &ReadyToBootEvent\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR,"Bds Set Memory Type Informationa Variable Fails\n"));\r
- }\r
-\r
}\r
\r
\r