-/** @file
-*
-* Copyright (c) 2011, ARM Limited. All rights reserved.
-*
-* 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 "BdsInternal.h"
-
-EFI_STATUS
-EditHIInputStr (
- IN OUT CHAR16 *CmdLine,
- IN UINTN MaxCmdLine
- )
-{
- UINTN CmdLineIndex;
- UINTN WaitIndex;
- CHAR8 Char;
- EFI_INPUT_KEY Key;
- EFI_STATUS Status;
-
- Print (CmdLine);
-
- for (CmdLineIndex = StrLen (CmdLine); CmdLineIndex < MaxCmdLine; ) {
- Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &WaitIndex);
- ASSERT_EFI_ERROR (Status);
-
- Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
- ASSERT_EFI_ERROR (Status);
-
- // Unicode character is valid when Scancode is NUll
- if (Key.ScanCode == SCAN_NULL) {
- // Scan code is NUll, hence read Unicode character
- Char = (CHAR8)Key.UnicodeChar;
- } else {
- Char = CHAR_NULL;
- }
-
- if ((Char == CHAR_LINEFEED) || (Char == CHAR_CARRIAGE_RETURN) || (Char == 0x7f)) {
- CmdLine[CmdLineIndex] = '\0';
- Print (L"\n\r");
-
- return EFI_SUCCESS;
- } else if ((Key.UnicodeChar == L'\b') || (Key.ScanCode == SCAN_LEFT) || (Key.ScanCode == SCAN_DELETE)){
- if (CmdLineIndex != 0) {
- CmdLineIndex--;
- Print (L"\b \b");
- }
- } else if ((Key.ScanCode == SCAN_ESC) || (Char == 0x1B) || (Char == 0x0)) {
- return EFI_INVALID_PARAMETER;
- } else {
- CmdLine[CmdLineIndex++] = Key.UnicodeChar;
- Print (L"%c", Key.UnicodeChar);
- }
- }
-
- return EFI_SUCCESS;
-}
-
-EFI_STATUS
-GetHIInputStr (
- IN OUT CHAR16 *CmdLine,
- IN UINTN MaxCmdLine
- )
-{
- EFI_STATUS Status;
-
- // For a new input just passed an empty string
- CmdLine[0] = L'\0';
-
- Status = EditHIInputStr (CmdLine, MaxCmdLine);
-
- return Status;
-}
-
-EFI_STATUS
-EditHIInputAscii (
- IN OUT CHAR8 *CmdLine,
- IN UINTN MaxCmdLine
- )
-{
- CHAR16* Str;
- EFI_STATUS Status;
-
- Str = (CHAR16*)AllocatePool (MaxCmdLine * sizeof(CHAR16));
- AsciiStrToUnicodeStr (CmdLine, Str);
-
- Status = EditHIInputStr (Str, MaxCmdLine);
-
- if (!EFI_ERROR(Status)) {
- UnicodeStrToAsciiStr (Str, CmdLine);
- }
- FreePool (Str);
-
- return Status;
-}
-
-EFI_STATUS
-GetHIInputAscii (
- IN OUT CHAR8 *CmdLine,
- IN UINTN MaxCmdLine
- )
-{
- // For a new input just passed an empty string
- CmdLine[0] = '\0';
-
- return EditHIInputAscii (CmdLine,MaxCmdLine);
-}
-
-EFI_STATUS
-GetHIInputInteger (
- OUT UINTN *Integer
- )
-{
- CHAR16 CmdLine[255];
- EFI_STATUS Status;
-
- CmdLine[0] = '\0';
- Status = EditHIInputStr (CmdLine, 255);
- if (!EFI_ERROR(Status)) {
- *Integer = StrDecimalToUintn (CmdLine);
- }
-
- return Status;
-}
-
-EFI_STATUS
-GetHIInputIP (
- OUT EFI_IP_ADDRESS *Ip
- )
-{
- CHAR16 CmdLine[255];
- CHAR16 *Str;
- EFI_STATUS Status;
-
- CmdLine[0] = '\0';
- Status = EditHIInputStr (CmdLine,255);
- if (!EFI_ERROR(Status)) {
- Str = CmdLine;
- Ip->v4.Addr[0] = (UINT8)StrDecimalToUintn (Str);
-
- Str = StrStr (Str, L".");
- if (Str == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- Ip->v4.Addr[1] = (UINT8)StrDecimalToUintn (++Str);
-
- Str = StrStr (Str, L".");
- if (Str == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- Ip->v4.Addr[2] = (UINT8)StrDecimalToUintn (++Str);
-
- Str = StrStr (Str, L".");
- if (Str == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- Ip->v4.Addr[3] = (UINT8)StrDecimalToUintn (++Str);
- }
-
- return Status;
-}
-
-EFI_STATUS
-GetHIInputBoolean (
- OUT BOOLEAN *Value
- )
-{
- CHAR16 CmdBoolean[2];
- EFI_STATUS Status;
-
- while(1) {
- Print (L"[y/n] ");
- Status = GetHIInputStr (CmdBoolean, 2);
- if (EFI_ERROR(Status)) {
- return Status;
- } else if ((CmdBoolean[0] == L'y') || (CmdBoolean[0] == L'Y')) {
- if (Value) *Value = TRUE;
- return EFI_SUCCESS;
- } else if ((CmdBoolean[0] == L'n') || (CmdBoolean[0] == L'N')) {
- if (Value) *Value = FALSE;
- return EFI_SUCCESS;
- }
- }
-}
-
-BOOLEAN
-HasFilePathEfiExtension (
- IN CHAR16* FilePath
- )
-{
- return (StrCmp (FilePath + (StrSize(FilePath)/sizeof(CHAR16)) - 5, L".efi") == 0);
-}
-
-// Return the last non end-type Device Path Node from a Device Path
-EFI_DEVICE_PATH*
-GetLastDevicePathNode (
- IN EFI_DEVICE_PATH* DevicePath
- )
-{
- EFI_DEVICE_PATH* PrevDevicePathNode;
-
- PrevDevicePathNode = DevicePath;
- while (!IsDevicePathEndType (DevicePath)) {
- PrevDevicePathNode = DevicePath;
- DevicePath = NextDevicePathNode (DevicePath);
- }
-
- return PrevDevicePathNode;
-}
-
-EFI_STATUS
-GenerateDeviceDescriptionName (
- IN EFI_HANDLE Handle,
- IN OUT CHAR16* Description
- )
-{
- EFI_STATUS Status;
- EFI_COMPONENT_NAME_PROTOCOL* ComponentName2Protocol;
- EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;
- EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;
- CHAR16* DriverName;
- CHAR16* DevicePathTxt;
- EFI_DEVICE_PATH* DevicePathNode;
-
- ComponentName2Protocol = NULL;
- Status = gBS->HandleProtocol (Handle, &gEfiComponentName2ProtocolGuid, (VOID **)&ComponentName2Protocol);
- if (!EFI_ERROR(Status)) {
- //TODO: Fixme. we must find the best langague
- Status = ComponentName2Protocol->GetDriverName (ComponentName2Protocol,"en",&DriverName);
- if (!EFI_ERROR(Status)) {
- StrnCpy (Description, DriverName, BOOT_DEVICE_DESCRIPTION_MAX);
- }
- }
-
- if (EFI_ERROR(Status)) {
- // Use the lastest non null entry of the Device path as a description
- Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);
- if (EFI_ERROR(Status)) {
- return Status;
- }
-
- // Convert the last non end-type Device Path Node in text for the description
- DevicePathNode = GetLastDevicePathNode (DevicePathProtocol);
- Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);
- ASSERT_EFI_ERROR(Status);
- DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (DevicePathNode, TRUE, TRUE);
- StrnCpy (Description, DevicePathTxt, BOOT_DEVICE_DESCRIPTION_MAX);
- FreePool (DevicePathTxt);
- }
-
- return EFI_SUCCESS;
-}
-
-EFI_STATUS
-BdsStartBootOption (
- IN CHAR16* BootOption
- )
-{
- EFI_STATUS Status;
- BDS_LOAD_OPTION *BdsLoadOption;
-
- Status = BootOptionFromLoadOptionVariable (BootOption, &BdsLoadOption);
- if (!EFI_ERROR(Status)) {
- Status = BootOptionStart (BdsLoadOption);
- FreePool (BdsLoadOption);
-
- if (!EFI_ERROR(Status)) {
- Status = EFI_SUCCESS;
- } else {
- Status = EFI_NOT_STARTED;
- }
- } else {
- Status = EFI_NOT_FOUND;
- }
- return Status;
-}
-
-UINTN
-GetUnalignedDevicePathSize (
- IN EFI_DEVICE_PATH* DevicePath
- )
-{
- UINTN Size;
- EFI_DEVICE_PATH* AlignedDevicePath;
-
- if ((UINTN)DevicePath & 0x1) {
- AlignedDevicePath = DuplicateDevicePath (DevicePath);
- Size = GetDevicePathSize (AlignedDevicePath);
- FreePool (AlignedDevicePath);
- } else {
- Size = GetDevicePathSize (DevicePath);
- }
- return Size;
-}
-
-EFI_DEVICE_PATH*
-GetAlignedDevicePath (
- IN EFI_DEVICE_PATH* DevicePath
- )
-{
- if ((UINTN)DevicePath & 0x1) {
- return DuplicateDevicePath (DevicePath);
- } else {
- return DevicePath;
- }
-}
-
+/** @file\r
+*\r
+* Copyright (c) 2011 - 2014, ARM Limited. All rights reserved.\r
+*\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 <Library/NetLib.h>\r
+#include "BdsInternal.h"\r
+\r
+EFI_STATUS\r
+EditHIInputStr (\r
+ IN OUT CHAR16 *CmdLine,\r
+ IN UINTN MaxCmdLine\r
+ )\r
+{\r
+ UINTN CmdLineIndex;\r
+ UINTN WaitIndex;\r
+ CHAR8 Char;\r
+ EFI_INPUT_KEY Key;\r
+ EFI_STATUS Status;\r
+\r
+ // The command line must be at least one character long\r
+ ASSERT (MaxCmdLine > 0);\r
+\r
+ // Ensure the last character of the buffer is the NULL character\r
+ CmdLine[MaxCmdLine - 1] = '\0';\r
+\r
+ Print (CmdLine);\r
+\r
+ // To prevent a buffer overflow, we only allow to enter (MaxCmdLine-1) characters\r
+ for (CmdLineIndex = StrLen (CmdLine); CmdLineIndex < MaxCmdLine; ) {\r
+ Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &WaitIndex);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ // Unicode character is valid when Scancode is NUll\r
+ if (Key.ScanCode == SCAN_NULL) {\r
+ // Scan code is NUll, hence read Unicode character\r
+ Char = (CHAR8)Key.UnicodeChar;\r
+ } else {\r
+ Char = CHAR_NULL;\r
+ }\r
+\r
+ if ((Char == CHAR_LINEFEED) || (Char == CHAR_CARRIAGE_RETURN) || (Char == 0x7f)) {\r
+ CmdLine[CmdLineIndex] = '\0';\r
+ Print (L"\r\n");\r
+\r
+ return EFI_SUCCESS;\r
+ } else if ((Key.UnicodeChar == L'\b') || (Key.ScanCode == SCAN_LEFT) || (Key.ScanCode == SCAN_DELETE)){\r
+ if (CmdLineIndex != 0) {\r
+ CmdLineIndex--;\r
+ Print (L"\b \b");\r
+ }\r
+ } else if ((Key.ScanCode == SCAN_ESC) || (Char == 0x1B) || (Char == 0x0)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ } else if (CmdLineIndex < (MaxCmdLine-1)) {\r
+ CmdLine[CmdLineIndex++] = Key.UnicodeChar;\r
+ Print (L"%c", Key.UnicodeChar);\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetHIInputStr (\r
+ IN OUT CHAR16 *CmdLine,\r
+ IN UINTN MaxCmdLine\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ // For a new input just passed an empty string\r
+ CmdLine[0] = L'\0';\r
+\r
+ Status = EditHIInputStr (CmdLine, MaxCmdLine);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EditHIInputAscii (\r
+ IN OUT CHAR8 *CmdLine,\r
+ IN UINTN MaxCmdLine\r
+ )\r
+{\r
+ CHAR16* Str;\r
+ EFI_STATUS Status;\r
+\r
+ Str = (CHAR16*)AllocatePool (MaxCmdLine * sizeof(CHAR16));\r
+ AsciiStrToUnicodeStr (CmdLine, Str);\r
+\r
+ Status = EditHIInputStr (Str, MaxCmdLine);\r
+ if (!EFI_ERROR(Status)) {\r
+ UnicodeStrToAsciiStr (Str, CmdLine);\r
+ }\r
+ FreePool (Str);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+GetHIInputAscii (\r
+ IN OUT CHAR8 *CmdLine,\r
+ IN UINTN MaxCmdLine\r
+ )\r
+{\r
+ // For a new input just passed an empty string\r
+ CmdLine[0] = '\0';\r
+\r
+ return EditHIInputAscii (CmdLine,MaxCmdLine);\r
+}\r
+\r
+EFI_STATUS\r
+GetHIInputInteger (\r
+ OUT UINTN *Integer\r
+ )\r
+{\r
+ CHAR16 CmdLine[255];\r
+ EFI_STATUS Status;\r
+\r
+ CmdLine[0] = '\0';\r
+ Status = EditHIInputStr (CmdLine, 255);\r
+ if (!EFI_ERROR(Status)) {\r
+ *Integer = StrDecimalToUintn (CmdLine);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Get an IPv4 address\r
+\r
+ The function asks the user for an IPv4 address. If the input\r
+ string defines a valid IPv4 address, the four bytes of the\r
+ corresponding IPv4 address are extracted from the string and returned by\r
+ the function. As long as the user does not define a valid IP\r
+ address, he is asked for one. He can always escape by\r
+ pressing ESC.\r
+\r
+ @param[out] EFI_IP_ADDRESS OutIpAddr Returned IPv4 address. Valid if\r
+ and only if the returned value\r
+ is equal to EFI_SUCCESS\r
+\r
+ @retval EFI_SUCCESS Input completed\r
+ @retval EFI_ABORTED Editing aborted by the user\r
+ @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to\r
+ lack of resource\r
+**/\r
+EFI_STATUS\r
+GetHIInputIP (\r
+ OUT EFI_IP_ADDRESS *OutIpAddr\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 CmdLine[48];\r
+\r
+ while (TRUE) {\r
+ CmdLine[0] = '\0';\r
+ Status = EditHIInputStr (CmdLine, 48);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ Status = NetLibStrToIp4 (CmdLine, &OutIpAddr->v4);\r
+ if (Status == EFI_INVALID_PARAMETER) {\r
+ Print (L"Invalid address\n");\r
+ } else {\r
+ return Status;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Edit an IPv4 address\r
+\r
+ The function displays as a string following the "%d.%d.%d.%d" format the\r
+ IPv4 address that is passed in and asks the user to modify it. If the\r
+ resulting string defines a valid IPv4 address, the four bytes of the\r
+ corresponding IPv4 address are extracted from the string and returned by\r
+ the function. As long as the user does not define a valid IP\r
+ address, he is asked for one. He can always escape by\r
+ pressing ESC.\r
+\r
+ @param[in ] EFI_IP_ADDRESS InIpAddr Input IPv4 address\r
+ @param[out] EFI_IP_ADDRESS OutIpAddr Returned IPv4 address. Valid if\r
+ and only if the returned value\r
+ is equal to EFI_SUCCESS\r
+\r
+ @retval EFI_SUCCESS Update completed\r
+ @retval EFI_ABORTED Editing aborted by the user\r
+ @retval EFI_INVALID_PARAMETER The string returned by the user is\r
+ mal-formated\r
+ @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to\r
+ lack of resource\r
+**/\r
+EFI_STATUS\r
+EditHIInputIP (\r
+ IN EFI_IP_ADDRESS *InIpAddr,\r
+ OUT EFI_IP_ADDRESS *OutIpAddr\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 CmdLine[48];\r
+\r
+ while (TRUE) {\r
+ UnicodeSPrint (\r
+ CmdLine, 48, L"%d.%d.%d.%d",\r
+ InIpAddr->v4.Addr[0], InIpAddr->v4.Addr[1],\r
+ InIpAddr->v4.Addr[2], InIpAddr->v4.Addr[3]\r
+ );\r
+\r
+ Status = EditHIInputStr (CmdLine, 48);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_ABORTED;\r
+ }\r
+ Status = NetLibStrToIp4 (CmdLine, &OutIpAddr->v4);\r
+ if (Status == EFI_INVALID_PARAMETER) {\r
+ Print (L"Invalid address\n");\r
+ } else {\r
+ return Status;\r
+ }\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+GetHIInputBoolean (\r
+ OUT BOOLEAN *Value\r
+ )\r
+{\r
+ CHAR16 CmdBoolean[2];\r
+ EFI_STATUS Status;\r
+\r
+ while(1) {\r
+ Print (L"[y/n] ");\r
+ Status = GetHIInputStr (CmdBoolean, 2);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ } else if ((CmdBoolean[0] == L'y') || (CmdBoolean[0] == L'Y')) {\r
+ if (Value) *Value = TRUE;\r
+ return EFI_SUCCESS;\r
+ } else if ((CmdBoolean[0] == L'n') || (CmdBoolean[0] == L'N')) {\r
+ if (Value) *Value = FALSE;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+}\r
+\r
+BOOLEAN\r
+HasFilePathEfiExtension (\r
+ IN CHAR16* FilePath\r
+ )\r
+{\r
+ return (StrCmp (FilePath + (StrSize (FilePath) / sizeof (CHAR16)) - 5, L".EFI") == 0) ||\r
+ (StrCmp (FilePath + (StrSize (FilePath) / sizeof (CHAR16)) - 5, L".efi") == 0);\r
+}\r
+\r
+// Return the last non end-type Device Path Node from a Device Path\r
+EFI_DEVICE_PATH*\r
+GetLastDevicePathNode (\r
+ IN EFI_DEVICE_PATH* DevicePath\r
+ )\r
+{\r
+ EFI_DEVICE_PATH* PrevDevicePathNode;\r
+\r
+ PrevDevicePathNode = DevicePath;\r
+ while (!IsDevicePathEndType (DevicePath)) {\r
+ PrevDevicePathNode = DevicePath;\r
+ DevicePath = NextDevicePathNode (DevicePath);\r
+ }\r
+\r
+ return PrevDevicePathNode;\r
+}\r
+\r
+EFI_STATUS\r
+GenerateDeviceDescriptionName (\r
+ IN EFI_HANDLE Handle,\r
+ IN OUT CHAR16* Description\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_COMPONENT_NAME_PROTOCOL* ComponentName2Protocol;\r
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
+ EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;\r
+ CHAR16* DriverName;\r
+ CHAR16* DevicePathTxt;\r
+ EFI_DEVICE_PATH* DevicePathNode;\r
+\r
+ ComponentName2Protocol = NULL;\r
+ Status = gBS->HandleProtocol (Handle, &gEfiComponentName2ProtocolGuid, (VOID **)&ComponentName2Protocol);\r
+ if (!EFI_ERROR(Status)) {\r
+ //TODO: Fixme. we must find the best langague\r
+ Status = ComponentName2Protocol->GetDriverName (ComponentName2Protocol,"en",&DriverName);\r
+ if (!EFI_ERROR(Status)) {\r
+ StrnCpy (Description, DriverName, BOOT_DEVICE_DESCRIPTION_MAX);\r
+ }\r
+ }\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ // Use the lastest non null entry of the Device path as a description\r
+ Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ // Convert the last non end-type Device Path Node in text for the description\r
+ DevicePathNode = GetLastDevicePathNode (DevicePathProtocol);\r
+ Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);\r
+ ASSERT_EFI_ERROR(Status);\r
+ DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (DevicePathNode, TRUE, TRUE);\r
+ StrnCpy (Description, DevicePathTxt, BOOT_DEVICE_DESCRIPTION_MAX);\r
+ FreePool (DevicePathTxt);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+BdsStartBootOption (\r
+ IN CHAR16* BootOption\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BDS_LOAD_OPTION *BdsLoadOption;\r
+\r
+ Status = BootOptionFromLoadOptionVariable (BootOption, &BdsLoadOption);\r
+ if (!EFI_ERROR(Status)) {\r
+ Status = BootOptionStart (BdsLoadOption);\r
+ FreePool (BdsLoadOption);\r
+\r
+ if (!EFI_ERROR(Status)) {\r
+ Status = EFI_SUCCESS;\r
+ } else {\r
+ Status = EFI_NOT_STARTED;\r
+ }\r
+ } else {\r
+ Status = EFI_NOT_FOUND;\r
+ }\r
+ return Status;\r
+}\r
+\r
+UINTN\r
+GetUnalignedDevicePathSize (\r
+ IN EFI_DEVICE_PATH* DevicePath\r
+ )\r
+{\r
+ UINTN Size;\r
+ EFI_DEVICE_PATH* AlignedDevicePath;\r
+\r
+ if ((UINTN)DevicePath & 0x1) {\r
+ AlignedDevicePath = DuplicateDevicePath (DevicePath);\r
+ Size = GetDevicePathSize (AlignedDevicePath);\r
+ FreePool (AlignedDevicePath);\r
+ } else {\r
+ Size = GetDevicePathSize (DevicePath);\r
+ }\r
+ return Size;\r
+}\r
+\r
+EFI_DEVICE_PATH*\r
+GetAlignedDevicePath (\r
+ IN EFI_DEVICE_PATH* DevicePath\r
+ )\r
+{\r
+ if ((UINTN)DevicePath & 0x1) {\r
+ return DuplicateDevicePath (DevicePath);\r
+ } else {\r
+ return DevicePath;\r
+ }\r
+}\r
+\r
+BOOLEAN\r
+IsUnicodeString (\r
+ IN VOID* String\r
+ )\r
+{\r
+ // We do not support NULL pointer\r
+ ASSERT (String != NULL);\r
+\r
+ if (*(CHAR16*)String < 0x100) {\r
+ //Note: We could get issue if the string is an empty Ascii string...\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/*\r
+ * Try to detect if the given string is an ASCII or Unicode string\r
+ *\r
+ * There are actually few limitation to this function but it is mainly to give\r
+ * a user friendly output.\r
+ *\r
+ * Some limitations:\r
+ * - it only supports unicode string that use ASCII character (< 0x100)\r
+ * - single character ASCII strings are interpreted as Unicode string\r
+ * - string cannot be longer than BOOT_DEVICE_OPTION_MAX characters and\r
+ * thus (BOOT_DEVICE_OPTION_MAX*2) bytes for an Unicode string and\r
+ * BOOT_DEVICE_OPTION_MAX bytes for an ASCII string.\r
+ *\r
+ * @param String Buffer that might contain a Unicode or Ascii string\r
+ * @param IsUnicode If not NULL this boolean value returns if the string is an\r
+ * ASCII or Unicode string.\r
+ */\r
+BOOLEAN\r
+IsPrintableString (\r
+ IN VOID* String,\r
+ OUT BOOLEAN *IsUnicode\r
+ )\r
+{\r
+ BOOLEAN UnicodeDetected;\r
+ BOOLEAN IsPrintable;\r
+ UINTN Index;\r
+ CHAR16 Character;\r
+\r
+ // We do not support NULL pointer\r
+ ASSERT (String != NULL);\r
+\r
+ // Test empty string\r
+ if (*(CHAR16*)String == L'\0') {\r
+ if (IsUnicode) {\r
+ *IsUnicode = TRUE;\r
+ }\r
+ return TRUE;\r
+ } else if (*(CHAR16*)String == '\0') {\r
+ if (IsUnicode) {\r
+ *IsUnicode = FALSE;\r
+ }\r
+ return TRUE;\r
+ }\r
+\r
+ // Limitation: if the string is an ASCII single character string. This comparison\r
+ // will assume it is a Unicode string.\r
+ if (*(CHAR16*)String < 0x100) {\r
+ UnicodeDetected = TRUE;\r
+ } else {\r
+ UnicodeDetected = FALSE;\r
+ }\r
+\r
+ IsPrintable = FALSE;\r
+ for (Index = 0; Index < BOOT_DEVICE_OPTION_MAX; Index++) {\r
+ if (UnicodeDetected) {\r
+ Character = ((CHAR16*)String)[Index];\r
+ } else {\r
+ Character = ((CHAR8*)String)[Index];\r
+ }\r
+\r
+ if (Character == '\0') {\r
+ // End of the string\r
+ IsPrintable = TRUE;\r
+ break;\r
+ } else if ((Character < 0x20) || (Character > 0x7f)) {\r
+ // We only support the range of printable ASCII character\r
+ IsPrintable = FALSE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (IsPrintable && IsUnicode) {\r
+ *IsUnicode = UnicodeDetected;\r
+ }\r
+\r
+ return IsPrintable;\r
+}\r