summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c')
-rw-r--r--MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c772
1 files changed, 386 insertions, 386 deletions
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c b/MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c
index 30d955111e..97d1a48cd5 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c
@@ -1,386 +1,386 @@
-/** @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
+ 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);
+ }
+}