]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c
MdeModulePkg: Fix EOL to be DOS format.
[mirror_edk2.git] / MdeModulePkg / Library / UefiBootManagerLib / BmMisc.c
index 30d955111ec8ae3032e8327a9bb771f21f299051..97d1a48cd5a24af336c09242f0e26bcd50e21611 100644 (file)
-/** @file
-  Misc library functions.
-
-Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
-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.
-
-**/
-
-#include "InternalBm.h"
-
-/**
-  Delete the instance in Multi which matches partly with Single instance
-
-  @param  Multi                 A pointer to a multi-instance device path data
-                                structure.
-  @param  Single                A pointer to a single-instance device path data
-                                structure.
-
-  @return This function will remove the device path instances in Multi which partly
-          match with the Single, and return the result device path. If there is no
-          remaining device path as a result, this function will return NULL.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-BmDelPartMatchInstance (
-  IN     EFI_DEVICE_PATH_PROTOCOL  *Multi,
-  IN     EFI_DEVICE_PATH_PROTOCOL  *Single
-  )
-{
-  EFI_DEVICE_PATH_PROTOCOL  *Instance;
-  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
-  EFI_DEVICE_PATH_PROTOCOL  *TempNewDevicePath;
-  UINTN                     InstanceSize;
-  UINTN                     SingleDpSize;
-
-  NewDevicePath     = NULL;
-  TempNewDevicePath = NULL;
-
-  if (Multi == NULL || Single == NULL) {
-    return Multi;
-  }
-
-  Instance        = GetNextDevicePathInstance (&Multi, &InstanceSize);
-  SingleDpSize    = GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH;
-  InstanceSize   -= END_DEVICE_PATH_LENGTH;
-
-  while (Instance != NULL) {
-
-    if (CompareMem (Instance, Single, MIN (SingleDpSize, InstanceSize)) != 0) {
-      //
-      // Append the device path instance which does not match with Single
-      //
-      TempNewDevicePath = NewDevicePath;
-      NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance);
-      if (TempNewDevicePath != NULL) {
-        FreePool(TempNewDevicePath);
-      }
-    }
-    FreePool(Instance);
-    Instance      = GetNextDevicePathInstance (&Multi, &InstanceSize);
-    InstanceSize -= END_DEVICE_PATH_LENGTH;
-  }
-
-  return NewDevicePath;
-}
-
-/**
-  Function compares a device path data structure to that of all the nodes of a
-  second device path instance.
-
-  @param  Multi                 A pointer to a multi-instance device path data
-                                structure.
-  @param  Single                A pointer to a single-instance device path data
-                                structure.
-
-  @retval TRUE                  If the Single device path is contained within Multi device path.
-  @retval FALSE                 The Single device path is not match within Multi device path.
-
-**/
-BOOLEAN
-BmMatchDevicePaths (
-  IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,
-  IN  EFI_DEVICE_PATH_PROTOCOL  *Single
-  )
-{
-  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
-  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;
-  UINTN                     Size;
-
-  if (Multi == NULL || Single  == NULL) {
-    return FALSE;
-  }
-
-  DevicePath     = Multi;
-  DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
-
-  //
-  // Search for the match of 'Single' in 'Multi'
-  //
-  while (DevicePathInst != NULL) {
-    //
-    // If the single device path is found in multiple device paths,
-    // return success
-    //
-    if (CompareMem (Single, DevicePathInst, Size) == 0) {
-      FreePool (DevicePathInst);
-      return TRUE;
-    }
-
-    FreePool (DevicePathInst);
-    DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
-  }
-
-  return FALSE;
-}
-
-/**
-  This routine adjust the memory information for different memory type and 
-  save them into the variables for next boot.
-**/
-VOID
-BmSetMemoryTypeInformationVariable (
-  VOID
-  )
-{
-  EFI_STATUS                   Status;
-  EFI_MEMORY_TYPE_INFORMATION  *PreviousMemoryTypeInformation;
-  EFI_MEMORY_TYPE_INFORMATION  *CurrentMemoryTypeInformation;
-  UINTN                        VariableSize;
-  UINTN                        Index;
-  UINTN                        Index1;
-  UINT32                       Previous;
-  UINT32                       Current;
-  UINT32                       Next;
-  EFI_HOB_GUID_TYPE            *GuidHob;
-  BOOLEAN                      MemoryTypeInformationModified;
-  BOOLEAN                      MemoryTypeInformationVariableExists;
-  EFI_BOOT_MODE                BootMode;
-
-  MemoryTypeInformationModified       = FALSE;
-  MemoryTypeInformationVariableExists = FALSE;
-
-
-  BootMode = GetBootModeHob ();
-  //
-  // In BOOT_IN_RECOVERY_MODE, Variable region is not reliable.
-  //
-  if (BootMode == BOOT_IN_RECOVERY_MODE) {
-    return;
-  }
-
-  //
-  // Only check the the Memory Type Information variable in the boot mode 
-  // other than BOOT_WITH_DEFAULT_SETTINGS because the Memory Type
-  // Information is not valid in this boot mode.
-  //
-  if (BootMode != BOOT_WITH_DEFAULT_SETTINGS) {
-    VariableSize = 0;
-    Status = gRT->GetVariable (
-                    EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
-                    &gEfiMemoryTypeInformationGuid,
-                    NULL, 
-                    &VariableSize, 
-                    NULL
-                    );
-    if (Status == EFI_BUFFER_TOO_SMALL) {
-      MemoryTypeInformationVariableExists = TRUE;
-    }
-  }
-
-  //
-  // Retrieve the current memory usage statistics.  If they are not found, then
-  // no adjustments can be made to the Memory Type Information variable.
-  //
-  Status = EfiGetSystemConfigurationTable (
-             &gEfiMemoryTypeInformationGuid,
-             (VOID **) &CurrentMemoryTypeInformation
-             );
-  if (EFI_ERROR (Status) || CurrentMemoryTypeInformation == NULL) {
-    return;
-  }
-
-  //
-  // Get the Memory Type Information settings from Hob if they exist,
-  // PEI is responsible for getting them from variable and build a Hob to save them.
-  // If the previous Memory Type Information is not available, then set defaults
-  //
-  GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
-  if (GuidHob == NULL) {
-    //
-    // If Platform has not built Memory Type Info into the Hob, just return.
-    //
-    return;
-  }
-  PreviousMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);
-  VariableSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
-
-  //
-  // Use a heuristic to adjust the Memory Type Information for the next boot
-  //
-  DEBUG ((EFI_D_INFO, "Memory  Previous  Current    Next   \n"));
-  DEBUG ((EFI_D_INFO, " Type    Pages     Pages     Pages  \n"));
-  DEBUG ((EFI_D_INFO, "======  ========  ========  ========\n"));
-
-  for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
-
-    for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) {
-      if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) {
-        break;
-      }
-    }
-    if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) {
-      continue;
-    }
-
-    //
-    // Previous is the number of pages pre-allocated
-    // Current is the number of pages actually needed
-    //
-    Previous = PreviousMemoryTypeInformation[Index].NumberOfPages;
-    Current  = CurrentMemoryTypeInformation[Index1].NumberOfPages;
-    Next     = Previous;
-
-    //
-    // Inconsistent Memory Reserved across bootings may lead to S4 fail
-    // Write next varible to 125% * current when the pre-allocated memory is:
-    //  1. More than 150% of needed memory and boot mode is BOOT_WITH_DEFAULT_SETTING
-    //  2. Less than the needed memory
-    //
-    if ((Current + (Current >> 1)) < Previous) {
-      if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
-        Next = Current + (Current >> 2);
-      }
-    } else if (Current > Previous) {
-      Next = Current + (Current >> 2);
-    }
-    if (Next > 0 && Next < 4) {
-      Next = 4;
-    }
-
-    if (Next != Previous) {
-      PreviousMemoryTypeInformation[Index].NumberOfPages = Next;
-      MemoryTypeInformationModified = TRUE;
-    }
-
-    DEBUG ((EFI_D_INFO, "  %02x    %08x  %08x  %08x\n", PreviousMemoryTypeInformation[Index].Type, Previous, Current, Next));
-  }
-
-  //
-  // If any changes were made to the Memory Type Information settings, then set the new variable value;
-  // Or create the variable in first boot.
-  //
-  if (MemoryTypeInformationModified || !MemoryTypeInformationVariableExists) {
-    Status = BmSetVariableAndReportStatusCodeOnError (
-               EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
-               &gEfiMemoryTypeInformationGuid,
-               EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS,
-               VariableSize,
-               PreviousMemoryTypeInformation
-               );
-
-    if (!EFI_ERROR (Status)) {
-      //
-      // If the Memory Type Information settings have been modified, then reset the platform
-      // so the new Memory Type Information setting will be used to guarantee that an S4
-      // entry/resume cycle will not fail.
-      //
-      if (MemoryTypeInformationModified) {
-        DEBUG ((EFI_D_INFO, "Memory Type Information settings change. Warm Reset!!!\n"));
-        gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
-      }
-    } else {
-      DEBUG ((EFI_D_ERROR, "Memory Type Information settings cannot be saved. OS S4 may fail!\n"));
-    }
-  }
-}
-
-/**
-  Set the variable and report the error through status code upon failure.
-
-  @param  VariableName           A Null-terminated string that is the name of the vendor's variable.
-                                 Each VariableName is unique for each VendorGuid. VariableName must
-                                 contain 1 or more characters. If VariableName is an empty string,
-                                 then EFI_INVALID_PARAMETER is returned.
-  @param  VendorGuid             A unique identifier for the vendor.
-  @param  Attributes             Attributes bitmask to set for the variable.
-  @param  DataSize               The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE, 
-                                 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or 
-                                 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero 
-                                 causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is 
-                                 set, then a SetVariable() call with a DataSize of zero will not cause any change to 
-                                 the variable value (the timestamp associated with the variable may be updated however 
-                                 even if no new data value is provided,see the description of the 
-                                 EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not 
-                                 be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). 
-  @param  Data                   The contents for the variable.
-
-  @retval EFI_SUCCESS            The firmware has successfully stored the variable and its data as
-                                 defined by the Attributes.
-  @retval EFI_INVALID_PARAMETER  An invalid combination of attribute bits, name, and GUID was supplied, or the
-                                 DataSize exceeds the maximum allowed.
-  @retval EFI_INVALID_PARAMETER  VariableName is an empty string.
-  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the variable and its data.
-  @retval EFI_DEVICE_ERROR       The variable could not be retrieved due to a hardware error.
-  @retval EFI_WRITE_PROTECTED    The variable in question is read-only.
-  @retval EFI_WRITE_PROTECTED    The variable in question cannot be deleted.
-  @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 
-                                 or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo 
-                                 does NOT pass the validation check carried out by the firmware.
-
-  @retval EFI_NOT_FOUND          The variable trying to be updated or deleted was not found.
-**/
-EFI_STATUS
-BmSetVariableAndReportStatusCodeOnError (
-  IN CHAR16     *VariableName,
-  IN EFI_GUID   *VendorGuid,
-  IN UINT32     Attributes,
-  IN UINTN      DataSize,
-  IN VOID       *Data
-  )
-{
-  EFI_STATUS                 Status;
-  EDKII_SET_VARIABLE_STATUS  *SetVariableStatus;
-  UINTN                      NameSize;
-
-  Status = gRT->SetVariable (
-                  VariableName,
-                  VendorGuid,
-                  Attributes,
-                  DataSize,
-                  Data
-                  );
-  if (EFI_ERROR (Status)) {
-    NameSize = StrSize (VariableName);
-    SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize);
-    if (SetVariableStatus != NULL) {
-      CopyGuid (&SetVariableStatus->Guid, VendorGuid);
-      SetVariableStatus->NameSize   = NameSize;
-      SetVariableStatus->DataSize   = DataSize;
-      SetVariableStatus->SetStatus  = Status;
-      SetVariableStatus->Attributes = Attributes;
-      CopyMem (SetVariableStatus + 1,                          VariableName, NameSize);
-      CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Data,         DataSize);
-
-      REPORT_STATUS_CODE_EX (
-        EFI_ERROR_CODE,
-        PcdGet32 (PcdErrorCodeSetVariable),
-        0,
-        NULL,
-        &gEdkiiStatusCodeDataTypeVariableGuid,
-        SetVariableStatus,
-        sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize
-        );
-
-      FreePool (SetVariableStatus);
-    }
-  }
-
-  return Status;
-}
-
-
-/**
-  Print the device path info.
-
-  @param DevicePath           The device path need to print.
-**/
-VOID
-BmPrintDp (
-  EFI_DEVICE_PATH_PROTOCOL            *DevicePath
-  )
-{
-  CHAR16                              *Str;
-
-  Str = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
-  DEBUG ((EFI_D_INFO, "%s", Str));
-  if (Str != NULL) {
-    FreePool (Str);
-  }
-}
+/** @file\r
+  Misc library functions.\r
+\r
+Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+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 "InternalBm.h"\r
+\r
+/**\r
+  Delete the instance in Multi which matches partly with Single instance\r
+\r
+  @param  Multi                 A pointer to a multi-instance device path data\r
+                                structure.\r
+  @param  Single                A pointer to a single-instance device path data\r
+                                structure.\r
+\r
+  @return This function will remove the device path instances in Multi which partly\r
+          match with the Single, and return the result device path. If there is no\r
+          remaining device path as a result, this function will return NULL.\r
+\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+BmDelPartMatchInstance (\r
+  IN     EFI_DEVICE_PATH_PROTOCOL  *Multi,\r
+  IN     EFI_DEVICE_PATH_PROTOCOL  *Single\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *Instance;\r
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *TempNewDevicePath;\r
+  UINTN                     InstanceSize;\r
+  UINTN                     SingleDpSize;\r
+\r
+  NewDevicePath     = NULL;\r
+  TempNewDevicePath = NULL;\r
+\r
+  if (Multi == NULL || Single == NULL) {\r
+    return Multi;\r
+  }\r
+\r
+  Instance        = GetNextDevicePathInstance (&Multi, &InstanceSize);\r
+  SingleDpSize    = GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH;\r
+  InstanceSize   -= END_DEVICE_PATH_LENGTH;\r
+\r
+  while (Instance != NULL) {\r
+\r
+    if (CompareMem (Instance, Single, MIN (SingleDpSize, InstanceSize)) != 0) {\r
+      //\r
+      // Append the device path instance which does not match with Single\r
+      //\r
+      TempNewDevicePath = NewDevicePath;\r
+      NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance);\r
+      if (TempNewDevicePath != NULL) {\r
+        FreePool(TempNewDevicePath);\r
+      }\r
+    }\r
+    FreePool(Instance);\r
+    Instance      = GetNextDevicePathInstance (&Multi, &InstanceSize);\r
+    InstanceSize -= END_DEVICE_PATH_LENGTH;\r
+  }\r
+\r
+  return NewDevicePath;\r
+}\r
+\r
+/**\r
+  Function compares a device path data structure to that of all the nodes of a\r
+  second device path instance.\r
+\r
+  @param  Multi                 A pointer to a multi-instance device path data\r
+                                structure.\r
+  @param  Single                A pointer to a single-instance device path data\r
+                                structure.\r
+\r
+  @retval TRUE                  If the Single device path is contained within Multi device path.\r
+  @retval FALSE                 The Single device path is not match within Multi device path.\r
+\r
+**/\r
+BOOLEAN\r
+BmMatchDevicePaths (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *Single\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;\r
+  UINTN                     Size;\r
+\r
+  if (Multi == NULL || Single  == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  DevicePath     = Multi;\r
+  DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
+\r
+  //\r
+  // Search for the match of 'Single' in 'Multi'\r
+  //\r
+  while (DevicePathInst != NULL) {\r
+    //\r
+    // If the single device path is found in multiple device paths,\r
+    // return success\r
+    //\r
+    if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
+      FreePool (DevicePathInst);\r
+      return TRUE;\r
+    }\r
+\r
+    FreePool (DevicePathInst);\r
+    DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\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
+BmSetMemoryTypeInformationVariable (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_MEMORY_TYPE_INFORMATION  *PreviousMemoryTypeInformation;\r
+  EFI_MEMORY_TYPE_INFORMATION  *CurrentMemoryTypeInformation;\r
+  UINTN                        VariableSize;\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
+  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 check 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
+  // no adjustments can be made to the Memory Type Information variable.\r
+  //\r
+  Status = EfiGetSystemConfigurationTable (\r
+             &gEfiMemoryTypeInformationGuid,\r
+             (VOID **) &CurrentMemoryTypeInformation\r
+             );\r
+  if (EFI_ERROR (Status) || CurrentMemoryTypeInformation == NULL) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Get the Memory Type Information settings from Hob if they exist,\r
+  // PEI is responsible for getting them from variable and build a Hob to save them.\r
+  // If the previous Memory Type Information is not available, then set defaults\r
+  //\r
+  GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);\r
+  if (GuidHob == NULL) {\r
+    //\r
+    // If Platform has not built Memory Type Info into the Hob, just return.\r
+    //\r
+    return;\r
+  }\r
+  PreviousMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);\r
+  VariableSize = GET_GUID_HOB_DATA_SIZE (GuidHob);\r
+\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
+    for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) {\r
+      if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) {\r
+        break;\r
+      }\r
+    }\r
+    if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Previous is the number of pages pre-allocated\r
+    // Current is the number of pages actually needed\r
+    //\r
+    Previous = PreviousMemoryTypeInformation[Index].NumberOfPages;\r
+    Current  = CurrentMemoryTypeInformation[Index1].NumberOfPages;\r
+    Next     = Previous;\r
+\r
+    //\r
+    // Inconsistent Memory Reserved across bootings may lead to S4 fail\r
+    // Write next varible to 125% * current when the pre-allocated memory is:\r
+    //  1. More than 150% of needed memory and boot mode is BOOT_WITH_DEFAULT_SETTING\r
+    //  2. Less than the needed memory\r
+    //\r
+    if ((Current + (Current >> 1)) < Previous) {\r
+      if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {\r
+        Next = Current + (Current >> 2);\r
+      }\r
+    } else if (Current > Previous) {\r
+      Next = Current + (Current >> 2);\r
+    }\r
+    if (Next > 0 && Next < 4) {\r
+      Next = 4;\r
+    }\r
+\r
+    if (Next != Previous) {\r
+      PreviousMemoryTypeInformation[Index].NumberOfPages = Next;\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
+  // Or create the variable in first boot.\r
+  //\r
+  if (MemoryTypeInformationModified || !MemoryTypeInformationVariableExists) {\r
+    Status = BmSetVariableAndReportStatusCodeOnError (\r
+               EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,\r
+               &gEfiMemoryTypeInformationGuid,\r
+               EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+               VariableSize,\r
+               PreviousMemoryTypeInformation\r
+               );\r
+\r
+    if (!EFI_ERROR (Status)) {\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) {\r
+        DEBUG ((EFI_D_INFO, "Memory Type Information settings change. Warm Reset!!!\n"));\r
+        gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
+      }\r
+    } else {\r
+      DEBUG ((EFI_D_ERROR, "Memory Type Information settings cannot be saved. OS S4 may fail!\n"));\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Set the variable and report the error through status code upon failure.\r
+\r
+  @param  VariableName           A Null-terminated string that is the name of the vendor's variable.\r
+                                 Each VariableName is unique for each VendorGuid. VariableName must\r
+                                 contain 1 or more characters. If VariableName is an empty string,\r
+                                 then EFI_INVALID_PARAMETER is returned.\r
+  @param  VendorGuid             A unique identifier for the vendor.\r
+  @param  Attributes             Attributes bitmask to set for the variable.\r
+  @param  DataSize               The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE, \r
+                                 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or \r
+                                 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero \r
+                                 causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is \r
+                                 set, then a SetVariable() call with a DataSize of zero will not cause any change to \r
+                                 the variable value (the timestamp associated with the variable may be updated however \r
+                                 even if no new data value is provided,see the description of the \r
+                                 EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not \r
+                                 be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). \r
+  @param  Data                   The contents for the variable.\r
+\r
+  @retval EFI_SUCCESS            The firmware has successfully stored the variable and its data as\r
+                                 defined by the Attributes.\r
+  @retval EFI_INVALID_PARAMETER  An invalid combination of attribute bits, name, and GUID was supplied, or the\r
+                                 DataSize exceeds the maximum allowed.\r
+  @retval EFI_INVALID_PARAMETER  VariableName is an empty string.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the variable and its data.\r
+  @retval EFI_DEVICE_ERROR       The variable could not be retrieved due to a hardware error.\r
+  @retval EFI_WRITE_PROTECTED    The variable in question is read-only.\r
+  @retval EFI_WRITE_PROTECTED    The variable in question cannot be deleted.\r
+  @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS \r
+                                 or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo \r
+                                 does NOT pass the validation check carried out by the firmware.\r
+\r
+  @retval EFI_NOT_FOUND          The variable trying to be updated or deleted was not found.\r
+**/\r
+EFI_STATUS\r
+BmSetVariableAndReportStatusCodeOnError (\r
+  IN CHAR16     *VariableName,\r
+  IN EFI_GUID   *VendorGuid,\r
+  IN UINT32     Attributes,\r
+  IN UINTN      DataSize,\r
+  IN VOID       *Data\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EDKII_SET_VARIABLE_STATUS  *SetVariableStatus;\r
+  UINTN                      NameSize;\r
+\r
+  Status = gRT->SetVariable (\r
+                  VariableName,\r
+                  VendorGuid,\r
+                  Attributes,\r
+                  DataSize,\r
+                  Data\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    NameSize = StrSize (VariableName);\r
+    SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize);\r
+    if (SetVariableStatus != NULL) {\r
+      CopyGuid (&SetVariableStatus->Guid, VendorGuid);\r
+      SetVariableStatus->NameSize   = NameSize;\r
+      SetVariableStatus->DataSize   = DataSize;\r
+      SetVariableStatus->SetStatus  = Status;\r
+      SetVariableStatus->Attributes = Attributes;\r
+      CopyMem (SetVariableStatus + 1,                          VariableName, NameSize);\r
+      CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Data,         DataSize);\r
+\r
+      REPORT_STATUS_CODE_EX (\r
+        EFI_ERROR_CODE,\r
+        PcdGet32 (PcdErrorCodeSetVariable),\r
+        0,\r
+        NULL,\r
+        &gEdkiiStatusCodeDataTypeVariableGuid,\r
+        SetVariableStatus,\r
+        sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize\r
+        );\r
+\r
+      FreePool (SetVariableStatus);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Print the device path info.\r
+\r
+  @param DevicePath           The device path need to print.\r
+**/\r
+VOID\r
+BmPrintDp (\r
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePath\r
+  )\r
+{\r
+  CHAR16                              *Str;\r
+\r
+  Str = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
+  DEBUG ((EFI_D_INFO, "%s", Str));\r
+  if (Str != NULL) {\r
+    FreePool (Str);\r
+  }\r
+}\r