+++ /dev/null
-/** @file\r
- Misc BDS library function\r
-\r
-Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "InternalBdsLib.h"\r
-\r
-\r
-#define MAX_STRING_LEN 200\r
-\r
-BOOLEAN mFeaturerSwitch = TRUE;\r
-BOOLEAN mResetRequired = FALSE;\r
-\r
-extern UINT16 gPlatformBootTimeOutDefault;\r
-\r
-/**\r
- The function will go through the driver option link list, load and start\r
- every driver the driver option device path point to.\r
-\r
- @param BdsDriverLists The header of the current driver option link list\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-BdsLibLoadDrivers (\r
- IN LIST_ENTRY *BdsDriverLists\r
- )\r
-{\r
- EFI_STATUS Status;\r
- LIST_ENTRY *Link;\r
- BDS_COMMON_OPTION *Option;\r
- EFI_HANDLE ImageHandle;\r
- EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
- UINTN ExitDataSize;\r
- CHAR16 *ExitData;\r
- BOOLEAN ReconnectAll;\r
-\r
- ReconnectAll = FALSE;\r
-\r
- //\r
- // Process the driver option\r
- //\r
- for (Link = BdsDriverLists->ForwardLink; Link != BdsDriverLists; Link = Link->ForwardLink) {\r
- Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
-\r
- //\r
- // If a load option is not marked as LOAD_OPTION_ACTIVE,\r
- // the boot manager will not automatically load the option.\r
- //\r
- if (!IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_ACTIVE)) {\r
- continue;\r
- }\r
-\r
- //\r
- // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,\r
- // then all of the EFI drivers in the system will be disconnected and\r
- // reconnected after the last driver load option is processed.\r
- //\r
- if (IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_FORCE_RECONNECT)) {\r
- ReconnectAll = TRUE;\r
- }\r
-\r
- //\r
- // Make sure the driver path is connected.\r
- //\r
- BdsLibConnectDevicePath (Option->DevicePath);\r
-\r
- //\r
- // Load and start the image that Driver#### describes\r
- //\r
- Status = gBS->LoadImage (\r
- FALSE,\r
- gImageHandle,\r
- Option->DevicePath,\r
- NULL,\r
- 0,\r
- &ImageHandle\r
- );\r
-\r
- if (!EFI_ERROR (Status)) {\r
- gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);\r
-\r
- //\r
- // Verify whether this image is a driver, if not,\r
- // exit it and continue to parse next load option\r
- //\r
- if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) {\r
- gBS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL);\r
- continue;\r
- }\r
-\r
- if (Option->LoadOptionsSize != 0) {\r
- ImageInfo->LoadOptionsSize = Option->LoadOptionsSize;\r
- ImageInfo->LoadOptions = Option->LoadOptions;\r
- }\r
- //\r
- // Before calling the image, enable the Watchdog Timer for\r
- // the 5 Minute period\r
- //\r
- gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
-\r
- Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData);\r
- DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Driver Return Status = %r\n", Status));\r
-\r
- //\r
- // Clear the Watchdog Timer after the image returns\r
- //\r
- gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
- }\r
- }\r
-\r
- //\r
- // Process the LOAD_OPTION_FORCE_RECONNECT driver option\r
- //\r
- if (ReconnectAll) {\r
- BdsLibDisconnectAllEfi ();\r
- BdsLibConnectAll ();\r
- }\r
-\r
-}\r
-\r
-/**\r
- Get the Option Number that does not used.\r
- Try to locate the specific option variable one by one utile find a free number.\r
-\r
- @param VariableName Indicate if the boot#### or driver#### option\r
-\r
- @return The Minimal Free Option Number\r
-\r
-**/\r
-UINT16\r
-BdsLibGetFreeOptionNumber (\r
- IN CHAR16 *VariableName\r
- )\r
-{\r
- UINTN Index;\r
- CHAR16 StrTemp[10];\r
- UINT16 *OptionBuffer;\r
- UINTN OptionSize;\r
-\r
- //\r
- // Try to find the minimum free number from 0, 1, 2, 3....\r
- //\r
- Index = 0;\r
- do {\r
- if (*VariableName == 'B') {\r
- UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Boot%04x", Index);\r
- } else {\r
- UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Driver%04x", Index);\r
- }\r
- //\r
- // try if the option number is used\r
- //\r
- OptionBuffer = BdsLibGetVariableAndSize (\r
- StrTemp,\r
- &gEfiGlobalVariableGuid,\r
- &OptionSize\r
- );\r
- if (OptionBuffer == NULL) {\r
- break;\r
- }\r
- FreePool(OptionBuffer);\r
- Index++;\r
- } while (TRUE);\r
-\r
- return ((UINT16) Index);\r
-}\r
-\r
-\r
-/**\r
- This function will register the new boot#### or driver#### option base on\r
- the VariableName. The new registered boot#### or driver#### will be linked\r
- to BdsOptionList and also update to the VariableName. After the boot#### or\r
- driver#### updated, the BootOrder or DriverOrder will also be updated.\r
-\r
- @param BdsOptionList The header of the boot#### or driver#### link list\r
- @param DevicePath The device path which the boot#### or driver####\r
- option present\r
- @param String The description of the boot#### or driver####\r
- @param VariableName Indicate if the boot#### or driver#### option\r
-\r
- @retval EFI_SUCCESS The boot#### or driver#### have been success\r
- registered\r
- @retval EFI_STATUS Return the status of gRT->SetVariable ().\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BdsLibRegisterNewOption (\r
- IN LIST_ENTRY *BdsOptionList,\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
- IN CHAR16 *String,\r
- IN CHAR16 *VariableName\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Index;\r
- UINT16 RegisterOptionNumber;\r
- UINT16 *TempOptionPtr;\r
- UINTN TempOptionSize;\r
- UINT16 *OptionOrderPtr;\r
- VOID *OptionPtr;\r
- UINTN OptionSize;\r
- UINT8 *TempPtr;\r
- EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;\r
- CHAR16 *Description;\r
- CHAR16 OptionName[10];\r
- BOOLEAN UpdateDescription;\r
- UINT16 BootOrderEntry;\r
- UINTN OrderItemNum;\r
-\r
- if (DevicePath == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- OptionPtr = NULL;\r
- OptionSize = 0;\r
- TempPtr = NULL;\r
- OptionDevicePath = NULL;\r
- Description = NULL;\r
- OptionOrderPtr = NULL;\r
- UpdateDescription = FALSE;\r
- Status = EFI_SUCCESS;\r
- ZeroMem (OptionName, sizeof (OptionName));\r
-\r
- TempOptionSize = 0;\r
- TempOptionPtr = BdsLibGetVariableAndSize (\r
- VariableName,\r
- &gEfiGlobalVariableGuid,\r
- &TempOptionSize\r
- );\r
- //\r
- // Compare with current option variable if the previous option is set in global variable.\r
- //\r
- for (Index = 0; Index < TempOptionSize / sizeof (UINT16); Index++) {\r
- //\r
- // TempOptionPtr must not be NULL if we have non-zero TempOptionSize.\r
- //\r
- ASSERT (TempOptionPtr != NULL);\r
-\r
- if (*VariableName == 'B') {\r
- UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", TempOptionPtr[Index]);\r
- } else {\r
- UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", TempOptionPtr[Index]);\r
- }\r
-\r
- OptionPtr = BdsLibGetVariableAndSize (\r
- OptionName,\r
- &gEfiGlobalVariableGuid,\r
- &OptionSize\r
- );\r
- if (OptionPtr == NULL) {\r
- continue;\r
- }\r
-\r
- //\r
- // Validate the variable.\r
- //\r
- if (!ValidateOption(OptionPtr, OptionSize)) {\r
- FreePool(OptionPtr);\r
- continue;\r
- }\r
-\r
- TempPtr = OptionPtr;\r
- TempPtr += sizeof (UINT32) + sizeof (UINT16);\r
- Description = (CHAR16 *) TempPtr;\r
- TempPtr += StrSize ((CHAR16 *) TempPtr);\r
- OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
-\r
- //\r
- // Notes: the description may will change base on the GetStringToken\r
- //\r
- if (CompareMem (OptionDevicePath, DevicePath, GetDevicePathSize (OptionDevicePath)) == 0) {\r
- if (CompareMem (Description, String, StrSize (Description)) == 0) {\r
- //\r
- // Got the option, so just return\r
- //\r
- FreePool (OptionPtr);\r
- FreePool (TempOptionPtr);\r
- return EFI_SUCCESS;\r
- } else {\r
- //\r
- // Option description changed, need update.\r
- //\r
- UpdateDescription = TRUE;\r
- FreePool (OptionPtr);\r
- break;\r
- }\r
- }\r
-\r
- FreePool (OptionPtr);\r
- }\r
-\r
- OptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (String);\r
- OptionSize += GetDevicePathSize (DevicePath);\r
- OptionPtr = AllocateZeroPool (OptionSize);\r
- ASSERT (OptionPtr != NULL);\r
-\r
- TempPtr = OptionPtr;\r
- *(UINT32 *) TempPtr = LOAD_OPTION_ACTIVE;\r
- TempPtr += sizeof (UINT32);\r
- *(UINT16 *) TempPtr = (UINT16) GetDevicePathSize (DevicePath);\r
- TempPtr += sizeof (UINT16);\r
- CopyMem (TempPtr, String, StrSize (String));\r
- TempPtr += StrSize (String);\r
- CopyMem (TempPtr, DevicePath, GetDevicePathSize (DevicePath));\r
-\r
- if (UpdateDescription) {\r
- //\r
- // The number in option#### to be updated.\r
- // In this case, we must have non-NULL TempOptionPtr.\r
- //\r
- ASSERT (TempOptionPtr != NULL);\r
- RegisterOptionNumber = TempOptionPtr[Index];\r
- } else {\r
- //\r
- // The new option#### number\r
- //\r
- RegisterOptionNumber = BdsLibGetFreeOptionNumber(VariableName);\r
- }\r
-\r
- if (*VariableName == 'B') {\r
- UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", RegisterOptionNumber);\r
- } else {\r
- UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", RegisterOptionNumber);\r
- }\r
-\r
- Status = gRT->SetVariable (\r
- OptionName,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- OptionSize,\r
- OptionPtr\r
- );\r
- //\r
- // Return if only need to update a changed description or fail to set option.\r
- //\r
- if (EFI_ERROR (Status) || UpdateDescription) {\r
- FreePool (OptionPtr);\r
- if (TempOptionPtr != NULL) {\r
- FreePool (TempOptionPtr);\r
- }\r
- return Status;\r
- }\r
-\r
- FreePool (OptionPtr);\r
-\r
- //\r
- // Update the option order variable\r
- //\r
-\r
- //\r
- // If no option order\r
- //\r
- if (TempOptionSize == 0) {\r
- BootOrderEntry = 0;\r
- Status = gRT->SetVariable (\r
- VariableName,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- sizeof (UINT16),\r
- &BootOrderEntry\r
- );\r
- if (TempOptionPtr != NULL) {\r
- FreePool (TempOptionPtr);\r
- }\r
- return Status;\r
- }\r
-\r
- //\r
- // TempOptionPtr must not be NULL if TempOptionSize is not zero.\r
- //\r
- ASSERT (TempOptionPtr != NULL);\r
- //\r
- // Append the new option number to the original option order\r
- //\r
- OrderItemNum = (TempOptionSize / sizeof (UINT16)) + 1 ;\r
- OptionOrderPtr = AllocateZeroPool ( OrderItemNum * sizeof (UINT16));\r
- ASSERT (OptionOrderPtr!= NULL);\r
- CopyMem (OptionOrderPtr, TempOptionPtr, (OrderItemNum - 1) * sizeof (UINT16));\r
-\r
- OptionOrderPtr[Index] = RegisterOptionNumber;\r
-\r
- Status = gRT->SetVariable (\r
- VariableName,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- OrderItemNum * sizeof (UINT16),\r
- OptionOrderPtr\r
- );\r
- FreePool (TempOptionPtr);\r
- FreePool (OptionOrderPtr);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Returns the size of a device path in bytes.\r
-\r
- This function returns the size, in bytes, of the device path data structure\r
- specified by DevicePath including the end of device path node. If DevicePath\r
- is NULL, then 0 is returned. If the length of the device path is bigger than\r
- MaxSize, also return 0 to indicate this is an invalidate device path.\r
-\r
- @param DevicePath A pointer to a device path data structure.\r
- @param MaxSize Max valid device path size. If big than this size,\r
- return error.\r
-\r
- @retval 0 An invalid device path.\r
- @retval Others The size of a device path in bytes.\r
-\r
-**/\r
-UINTN\r
-GetDevicePathSizeEx (\r
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
- IN UINTN MaxSize\r
- )\r
-{\r
- UINTN Size;\r
- UINTN NodeSize;\r
-\r
- if (DevicePath == NULL) {\r
- return 0;\r
- }\r
-\r
- //\r
- // Search for the end of the device path structure\r
- //\r
- Size = 0;\r
- while (!IsDevicePathEnd (DevicePath)) {\r
- NodeSize = DevicePathNodeLength (DevicePath);\r
- if (NodeSize < END_DEVICE_PATH_LENGTH) {\r
- return 0;\r
- }\r
- Size += NodeSize;\r
- if (Size > MaxSize) {\r
- return 0;\r
- }\r
- DevicePath = NextDevicePathNode (DevicePath);\r
- }\r
- Size += DevicePathNodeLength (DevicePath);\r
- if (Size > MaxSize) {\r
- return 0;\r
- }\r
-\r
- return Size;\r
-}\r
-\r
-/**\r
- Returns the length of a Null-terminated Unicode string. If the length is\r
- bigger than MaxStringLen, return length 0 to indicate that this is an\r
- invalidate string.\r
-\r
- This function returns the byte length of Unicode characters in the Null-terminated\r
- Unicode string specified by String.\r
-\r
- If String is NULL, then ASSERT().\r
- If String is not aligned on a 16-bit boundary, then ASSERT().\r
-\r
- @param String A pointer to a Null-terminated Unicode string.\r
- @param MaxStringLen Max string len in this string.\r
-\r
- @retval 0 An invalid string.\r
- @retval Others The length of String.\r
-\r
-**/\r
-UINTN\r
-StrSizeEx (\r
- IN CONST CHAR16 *String,\r
- IN UINTN MaxStringLen\r
- )\r
-{\r
- UINTN Length;\r
-\r
- ASSERT (String != NULL && MaxStringLen != 0);\r
- ASSERT (((UINTN) String & BIT0) == 0);\r
-\r
- for (Length = 0; *String != L'\0' && MaxStringLen != Length; String++, Length+=2);\r
-\r
- if (*String != L'\0' && MaxStringLen == Length) {\r
- return 0;\r
- }\r
-\r
- return Length + 2;\r
-}\r
-\r
-/**\r
- Validate the EFI Boot#### variable (VendorGuid/Name)\r
-\r
- @param Variable Boot#### variable data.\r
- @param VariableSize Returns the size of the EFI variable that was read\r
-\r
- @retval TRUE The variable data is correct.\r
- @retval FALSE The variable data is corrupted.\r
-\r
-**/\r
-BOOLEAN\r
-ValidateOption (\r
- UINT8 *Variable,\r
- UINTN VariableSize\r
- )\r
-{\r
- UINT16 FilePathSize;\r
- UINT8 *TempPtr;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- UINTN TempSize;\r
-\r
- if (VariableSize <= sizeof (UINT16) + sizeof (UINT32)) {\r
- return FALSE;\r
- }\r
-\r
- //\r
- // Skip the option attribute\r
- //\r
- TempPtr = Variable;\r
- TempPtr += sizeof (UINT32);\r
-\r
- //\r
- // Get the option's device path size\r
- //\r
- FilePathSize = *(UINT16 *) TempPtr;\r
- TempPtr += sizeof (UINT16);\r
-\r
- //\r
- // Get the option's description string size\r
- //\r
- TempSize = StrSizeEx ((CHAR16 *) TempPtr, VariableSize - sizeof (UINT16) - sizeof (UINT32));\r
- TempPtr += TempSize;\r
-\r
- //\r
- // Get the option's device path\r
- //\r
- DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
- TempPtr += FilePathSize;\r
-\r
- //\r
- // Validation boot option variable.\r
- //\r
- if ((FilePathSize == 0) || (TempSize == 0)) {\r
- return FALSE;\r
- }\r
-\r
- if (TempSize + FilePathSize + sizeof (UINT16) + sizeof (UINT32) > VariableSize) {\r
- return FALSE;\r
- }\r
-\r
- return (BOOLEAN) (GetDevicePathSizeEx (DevicePath, FilePathSize) != 0);\r
-}\r
-\r
-/**\r
- Convert a single character to number.\r
- It assumes the input Char is in the scope of L'0' ~ L'9' and L'A' ~ L'F'\r
-\r
- @param Char The input char which need to change to a hex number.\r
-\r
-**/\r
-UINTN\r
-CharToUint (\r
- IN CHAR16 Char\r
- )\r
-{\r
- if ((Char >= L'0') && (Char <= L'9')) {\r
- return (Char - L'0');\r
- }\r
-\r
- if ((Char >= L'A') && (Char <= L'F')) {\r
- return (Char - L'A' + 0xA);\r
- }\r
-\r
- ASSERT (FALSE);\r
- return 0;\r
-}\r
-\r
-/**\r
- Build the boot#### or driver#### option from the VariableName, the\r
- build boot#### or driver#### will also be linked to BdsCommonOptionList.\r
-\r
- @param BdsCommonOptionList The header of the boot#### or driver#### option\r
- link list\r
- @param VariableName EFI Variable name indicate if it is boot#### or\r
- driver####\r
-\r
- @retval BDS_COMMON_OPTION Get the option just been created\r
- @retval NULL Failed to get the new option\r
-\r
-**/\r
-BDS_COMMON_OPTION *\r
-EFIAPI\r
-BdsLibVariableToOption (\r
- IN OUT LIST_ENTRY *BdsCommonOptionList,\r
- IN CHAR16 *VariableName\r
- )\r
-{\r
- UINT32 Attribute;\r
- UINT16 FilePathSize;\r
- UINT8 *Variable;\r
- UINT8 *TempPtr;\r
- UINTN VariableSize;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- BDS_COMMON_OPTION *Option;\r
- VOID *LoadOptions;\r
- UINT32 LoadOptionsSize;\r
- CHAR16 *Description;\r
- UINT8 NumOff;\r
-\r
- //\r
- // Read the variable. We will never free this data.\r
- //\r
- Variable = BdsLibGetVariableAndSize (\r
- VariableName,\r
- &gEfiGlobalVariableGuid,\r
- &VariableSize\r
- );\r
- if (Variable == NULL) {\r
- return NULL;\r
- }\r
-\r
- //\r
- // Validate Boot#### variable data.\r
- //\r
- if (!ValidateOption(Variable, VariableSize)) {\r
- FreePool (Variable);\r
- return NULL;\r
- }\r
-\r
- //\r
- // Notes: careful defined the variable of Boot#### or\r
- // Driver####, consider use some macro to abstract the code\r
- //\r
- //\r
- // Get the option attribute\r
- //\r
- TempPtr = Variable;\r
- Attribute = *(UINT32 *) Variable;\r
- TempPtr += sizeof (UINT32);\r
-\r
- //\r
- // Get the option's device path size\r
- //\r
- FilePathSize = *(UINT16 *) TempPtr;\r
- TempPtr += sizeof (UINT16);\r
-\r
- //\r
- // Get the option's description string\r
- //\r
- Description = (CHAR16 *) TempPtr;\r
-\r
- //\r
- // Get the option's description string size\r
- //\r
- TempPtr += StrSize((CHAR16 *) TempPtr);\r
-\r
- //\r
- // Get the option's device path\r
- //\r
- DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
- TempPtr += FilePathSize;\r
-\r
- //\r
- // Get load opion data.\r
- //\r
- LoadOptions = TempPtr;\r
- LoadOptionsSize = (UINT32) (VariableSize - ((UINTN)TempPtr - (UINTN)Variable));\r
-\r
- //\r
- // The Console variables may have multiple device paths, so make\r
- // an Entry for each one.\r
- //\r
- Option = AllocateZeroPool (sizeof (BDS_COMMON_OPTION));\r
- if (Option == NULL) {\r
- FreePool (Variable);\r
- return NULL;\r
- }\r
-\r
- Option->Signature = BDS_LOAD_OPTION_SIGNATURE;\r
- Option->DevicePath = AllocateZeroPool (GetDevicePathSize (DevicePath));\r
- ASSERT(Option->DevicePath != NULL);\r
- CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));\r
-\r
- Option->Attribute = Attribute;\r
- Option->Description = AllocateZeroPool (StrSize (Description));\r
- ASSERT(Option->Description != NULL);\r
- CopyMem (Option->Description, Description, StrSize (Description));\r
-\r
- Option->LoadOptions = AllocateZeroPool (LoadOptionsSize);\r
- ASSERT(Option->LoadOptions != NULL);\r
- CopyMem (Option->LoadOptions, LoadOptions, LoadOptionsSize);\r
- Option->LoadOptionsSize = LoadOptionsSize;\r
-\r
- //\r
- // Get the value from VariableName Unicode string\r
- // since the ISO standard assumes ASCII equivalent abbreviations, we can be safe in converting this\r
- // Unicode stream to ASCII without any loss in meaning.\r
- //\r
- if (*VariableName == 'B') {\r
- NumOff = (UINT8) (sizeof (L"Boot") / sizeof (CHAR16) - 1);\r
- Option->BootCurrent = (UINT16) (CharToUint (VariableName[NumOff+0]) * 0x1000)\r
- + (UINT16) (CharToUint (VariableName[NumOff+1]) * 0x100)\r
- + (UINT16) (CharToUint (VariableName[NumOff+2]) * 0x10)\r
- + (UINT16) (CharToUint (VariableName[NumOff+3]) * 0x1);\r
- }\r
- InsertTailList (BdsCommonOptionList, &Option->Link);\r
- FreePool (Variable);\r
- return Option;\r
-}\r
-\r
-/**\r
- Process BootOrder, or DriverOrder variables, by calling\r
- BdsLibVariableToOption () for each UINT16 in the variables.\r
-\r
- @param BdsCommonOptionList The header of the option list base on variable\r
- VariableName\r
- @param VariableName EFI Variable name indicate the BootOrder or\r
- DriverOrder\r
-\r
- @retval EFI_SUCCESS Success create the boot option or driver option\r
- list\r
- @retval EFI_OUT_OF_RESOURCES Failed to get the boot option or driver option list\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BdsLibBuildOptionFromVar (\r
- IN LIST_ENTRY *BdsCommonOptionList,\r
- IN CHAR16 *VariableName\r
- )\r
-{\r
- UINT16 *OptionOrder;\r
- UINTN OptionOrderSize;\r
- UINTN Index;\r
- BDS_COMMON_OPTION *Option;\r
- CHAR16 OptionName[20];\r
-\r
- //\r
- // Zero Buffer in order to get all BOOT#### variables\r
- //\r
- ZeroMem (OptionName, sizeof (OptionName));\r
-\r
- //\r
- // Read the BootOrder, or DriverOrder variable.\r
- //\r
- OptionOrder = BdsLibGetVariableAndSize (\r
- VariableName,\r
- &gEfiGlobalVariableGuid,\r
- &OptionOrderSize\r
- );\r
- if (OptionOrder == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {\r
- if (*VariableName == 'B') {\r
- UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionOrder[Index]);\r
- } else {\r
- UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", OptionOrder[Index]);\r
- }\r
-\r
- Option = BdsLibVariableToOption (BdsCommonOptionList, OptionName);\r
- if (Option != NULL) {\r
- Option->BootCurrent = OptionOrder[Index];\r
- }\r
- }\r
-\r
- FreePool (OptionOrder);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Get boot mode by looking up configuration table and parsing HOB list\r
-\r
- @param BootMode Boot mode from PEI handoff HOB.\r
-\r
- @retval EFI_SUCCESS Successfully get boot mode\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BdsLibGetBootMode (\r
- OUT EFI_BOOT_MODE *BootMode\r
- )\r
-{\r
- *BootMode = GetBootModeHob ();\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
- buffer, and the size of the buffer. If failure return NULL.\r
-\r
- @param Name String part of EFI variable name\r
- @param VendorGuid GUID part of EFI variable name\r
- @param VariableSize Returns the size of the EFI variable that was read\r
-\r
- @return Dynamically allocated memory that contains a copy of the EFI variable\r
- Caller is responsible freeing the buffer.\r
- @retval NULL Variable was not read\r
-\r
-**/\r
-VOID *\r
-EFIAPI\r
-BdsLibGetVariableAndSize (\r
- IN CHAR16 *Name,\r
- IN EFI_GUID *VendorGuid,\r
- OUT UINTN *VariableSize\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN BufferSize;\r
- VOID *Buffer;\r
-\r
- Buffer = NULL;\r
-\r
- //\r
- // Pass in a zero size buffer to find the required buffer size.\r
- //\r
- BufferSize = 0;\r
- Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- //\r
- // Allocate the buffer to return\r
- //\r
- Buffer = AllocateZeroPool (BufferSize);\r
- if (Buffer == NULL) {\r
- *VariableSize = 0;\r
- return NULL;\r
- }\r
- //\r
- // Read variable into the allocated buffer.\r
- //\r
- Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
- if (EFI_ERROR (Status)) {\r
- FreePool (Buffer);\r
- BufferSize = 0;\r
- Buffer = NULL;\r
- }\r
- }\r
-\r
- ASSERT (((Buffer == NULL) && (BufferSize == 0)) ||\r
- ((Buffer != NULL) && (BufferSize != 0))\r
- );\r
- *VariableSize = BufferSize;\r
- return Buffer;\r
-}\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
-EFIAPI\r
-BdsLibDelPartMatchInstance (\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
- UINTN Size;\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
- Size = (SingleDpSize < InstanceSize) ? SingleDpSize : InstanceSize;\r
-\r
- if ((CompareMem (Instance, Single, Size) != 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
-EFIAPI\r
-BdsLibMatchDevicePaths (\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 function prints a series of strings.\r
-\r
- @param ConOut Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL\r
- @param ... A variable argument list containing series of\r
- strings, the last string must be NULL.\r
-\r
- @retval EFI_SUCCESS Success print out the string using ConOut.\r
- @retval EFI_STATUS Return the status of the ConOut->OutputString ().\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BdsLibOutputStrings (\r
- IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut,\r
- ...\r
- )\r
-{\r
- VA_LIST Args;\r
- EFI_STATUS Status;\r
- CHAR16 *String;\r
-\r
- Status = EFI_SUCCESS;\r
- VA_START (Args, ConOut);\r
-\r
- while (!EFI_ERROR (Status)) {\r
- //\r
- // If String is NULL, then it's the end of the list\r
- //\r
- String = VA_ARG (Args, CHAR16 *);\r
- if (String == NULL) {\r
- break;\r
- }\r
-\r
- Status = ConOut->OutputString (ConOut, String);\r
-\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
- }\r
-\r
- VA_END(Args);\r
- return Status;\r
-}\r
-\r
-//\r
-// Following are BDS Lib functions which contain all the code about setup browser reset reminder feature.\r
-// Setup Browser reset reminder feature is that an reset reminder will be given before user leaves the setup browser if\r
-// user change any option setting which needs a reset to be effective, and the reset will be applied according to the user selection.\r
-//\r
-\r
-\r
-/**\r
- Enable the setup browser reset reminder feature.\r
- This routine is used in platform tip. If the platform policy need the feature, use the routine to enable it.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-EnableResetReminderFeature (\r
- VOID\r
- )\r
-{\r
- mFeaturerSwitch = TRUE;\r
-}\r
-\r
-\r
-/**\r
- Disable the setup browser reset reminder feature.\r
- This routine is used in platform tip. If the platform policy do not want the feature, use the routine to disable it.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-DisableResetReminderFeature (\r
- VOID\r
- )\r
-{\r
- mFeaturerSwitch = FALSE;\r
-}\r
-\r
-\r
-/**\r
- Record the info that a reset is required.\r
- A module boolean variable is used to record whether a reset is required.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-EnableResetRequired (\r
- VOID\r
- )\r
-{\r
- mResetRequired = TRUE;\r
-}\r
-\r
-\r
-/**\r
- Record the info that no reset is required.\r
- A module boolean variable is used to record whether a reset is required.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-DisableResetRequired (\r
- VOID\r
- )\r
-{\r
- mResetRequired = FALSE;\r
-}\r
-\r
-\r
-/**\r
- Check whether platform policy enable the reset reminder feature. The default is enabled.\r
-\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-IsResetReminderFeatureEnable (\r
- VOID\r
- )\r
-{\r
- return mFeaturerSwitch;\r
-}\r
-\r
-\r
-/**\r
- Check if user changed any option setting which needs a system reset to be effective.\r
-\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-IsResetRequired (\r
- VOID\r
- )\r
-{\r
- return mResetRequired;\r
-}\r
-\r
-\r
-/**\r
- Check whether a reset is needed, and finish the reset reminder feature.\r
- If a reset is needed, Popup a menu to notice user, and finish the feature\r
- according to the user selection.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-SetupResetReminder (\r
- VOID\r
- )\r
-{\r
- EFI_INPUT_KEY Key;\r
- CHAR16 *StringBuffer1;\r
- CHAR16 *StringBuffer2;\r
-\r
-\r
- //\r
- //check any reset required change is applied? if yes, reset system\r
- //\r
- if (IsResetReminderFeatureEnable ()) {\r
- if (IsResetRequired ()) {\r
-\r
- StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
- ASSERT (StringBuffer1 != NULL);\r
- StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
- ASSERT (StringBuffer2 != NULL);\r
- StrCpyS (\r
- StringBuffer1,\r
- MAX_STRING_LEN,\r
- L"Configuration changed. Reset to apply it Now."\r
- );\r
- StrCpyS (\r
- StringBuffer2,\r
- MAX_STRING_LEN,\r
- L"Press ENTER to reset"\r
- );\r
- //\r
- // Popup a menu to notice user\r
- //\r
- do {\r
- CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL);\r
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
-\r
- FreePool (StringBuffer1);\r
- FreePool (StringBuffer2);\r
-\r
- gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
- }\r
- }\r
-}\r
-\r
-/**\r
- Get the headers (dos, image, optional header) from an image\r
-\r
- @param Device SimpleFileSystem device handle\r
- @param FileName File name for the image\r
- @param DosHeader Pointer to dos header\r
- @param Hdr The buffer in which to return the PE32, PE32+, or TE header.\r
-\r
- @retval EFI_SUCCESS Successfully get the machine type.\r
- @retval EFI_NOT_FOUND The file is not found.\r
- @retval EFI_LOAD_ERROR File is not a valid image file.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BdsLibGetImageHeader (\r
- IN EFI_HANDLE Device,\r
- IN CHAR16 *FileName,\r
- OUT EFI_IMAGE_DOS_HEADER *DosHeader,\r
- OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
- EFI_FILE_HANDLE Root;\r
- EFI_FILE_HANDLE ThisFile;\r
- UINTN BufferSize;\r
- UINT64 FileSize;\r
- EFI_FILE_INFO *Info;\r
-\r
- Root = NULL;\r
- ThisFile = NULL;\r
- //\r
- // Handle the file system interface to the device\r
- //\r
- Status = gBS->HandleProtocol (\r
- Device,\r
- &gEfiSimpleFileSystemProtocolGuid,\r
- (VOID *) &Volume\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- Status = Volume->OpenVolume (\r
- Volume,\r
- &Root\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Root = NULL;\r
- goto Done;\r
- }\r
- ASSERT (Root != NULL);\r
- Status = Root->Open (Root, &ThisFile, FileName, EFI_FILE_MODE_READ, 0);\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- ASSERT (ThisFile != NULL);\r
-\r
- //\r
- // Get file size\r
- //\r
- BufferSize = SIZE_OF_EFI_FILE_INFO + 200;\r
- do {\r
- Info = NULL;\r
- Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info);\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- Status = ThisFile->GetInfo (\r
- ThisFile,\r
- &gEfiFileInfoGuid,\r
- &BufferSize,\r
- Info\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- break;\r
- }\r
- if (Status != EFI_BUFFER_TOO_SMALL) {\r
- FreePool (Info);\r
- goto Done;\r
- }\r
- FreePool (Info);\r
- } while (TRUE);\r
-\r
- FileSize = Info->FileSize;\r
- FreePool (Info);\r
-\r
- //\r
- // Read dos header\r
- //\r
- BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);\r
- Status = ThisFile->Read (ThisFile, &BufferSize, DosHeader);\r
- if (EFI_ERROR (Status) ||\r
- BufferSize < sizeof (EFI_IMAGE_DOS_HEADER) ||\r
- FileSize <= DosHeader->e_lfanew ||\r
- DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
- Status = EFI_LOAD_ERROR;\r
- goto Done;\r
- }\r
-\r
- //\r
- // Move to PE signature\r
- //\r
- Status = ThisFile->SetPosition (ThisFile, DosHeader->e_lfanew);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_LOAD_ERROR;\r
- goto Done;\r
- }\r
-\r
- //\r
- // Read and check PE signature\r
- //\r
- BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);\r
- Status = ThisFile->Read (ThisFile, &BufferSize, Hdr.Pe32);\r
- if (EFI_ERROR (Status) ||\r
- BufferSize < sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) ||\r
- Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
- Status = EFI_LOAD_ERROR;\r
- goto Done;\r
- }\r
-\r
- //\r
- // Check PE32 or PE32+ magic\r
- //\r
- if (Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC &&\r
- Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
- Status = EFI_LOAD_ERROR;\r
- goto Done;\r
- }\r
-\r
- Done:\r
- if (ThisFile != NULL) {\r
- ThisFile->Close (ThisFile);\r
- }\r
- if (Root != NULL) {\r
- Root->Close (Root);\r
- }\r
- return Status;\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
-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
- 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 = SetVariableAndReportStatusCodeOnError (\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 && 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
- } else {\r
- DEBUG ((EFI_D_ERROR, "Memory Type Information settings cannot be saved. OS S4 may fail!\n"));\r
- }\r
- }\r
-}\r
-\r
-/**\r
- This routine is kept for backward compatibility.\r
-**/\r
-VOID\r
-EFIAPI\r
-BdsLibSaveMemoryTypeInformation (\r
- VOID\r
- )\r
-{\r
-}\r
-\r
-\r
-/**\r
- Identify a user and, if authenticated, returns the current user profile handle.\r
-\r
- @param[out] User Point to user profile handle.\r
-\r
- @retval EFI_SUCCESS User is successfully identified, or user identification\r
- is not supported.\r
- @retval EFI_ACCESS_DENIED User is not successfully identified\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BdsLibUserIdentify (\r
- OUT EFI_USER_PROFILE_HANDLE *User\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_USER_MANAGER_PROTOCOL *Manager;\r
-\r
- Status = gBS->LocateProtocol (\r
- &gEfiUserManagerProtocolGuid,\r
- NULL,\r
- (VOID **) &Manager\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- return Manager->Identify (Manager, User);\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
-SetVariableAndReportStatusCodeOnError (\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
- if ((Data != NULL) && (DataSize != 0)) {\r
- CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Data, DataSize);\r
- }\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