/** @file\r
*\r
-* Copyright (c) 2011-2013, ARM Limited. All rights reserved.\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
*\r
**/\r
\r
+#include <Library/NetLib.h>\r
#include "BdsInternal.h"\r
\r
EFI_STATUS\r
// The command line must be at least one character long\r
ASSERT (MaxCmdLine > 0);\r
\r
- Print (CmdLine);\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-1; ) {\r
+ for (CmdLineIndex = StrLen (CmdLine); CmdLineIndex < MaxCmdLine; ) {
Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &WaitIndex);\r
ASSERT_EFI_ERROR (Status);\r
\r
\r
if ((Char == CHAR_LINEFEED) || (Char == CHAR_CARRIAGE_RETURN) || (Char == 0x7f)) {\r
CmdLine[CmdLineIndex] = '\0';\r
- Print (L"\n\r");\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
}\r
} else if ((Key.ScanCode == SCAN_ESC) || (Char == 0x1B) || (Char == 0x0)) {\r
return EFI_INVALID_PARAMETER;\r
- } else {\r
+ } else if (CmdLineIndex < (MaxCmdLine-1)) {
CmdLine[CmdLineIndex++] = Key.UnicodeChar;\r
Print (L"%c", Key.UnicodeChar);\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
+
+ @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 *Ip\r
+ OUT EFI_IP_ADDRESS *OutIpAddr\r
)\r
{\r
- CHAR16 CmdLine[255];\r
- CHAR16 *Str;\r
EFI_STATUS Status;\r
+ CHAR16 CmdLine[48];\r
\r
- CmdLine[0] = '\0';\r
- Status = EditHIInputStr (CmdLine,255);\r
- if (!EFI_ERROR(Status)) {\r
- Str = CmdLine;\r
- Ip->v4.Addr[0] = (UINT8)StrDecimalToUintn (Str);\r
-\r
- Str = StrStr (Str, L".");\r
- if (Str == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
+ while (TRUE) {\r
+ CmdLine[0] = '\0';\r
+ Status = EditHIInputStr (CmdLine, 48);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_ABORTED;\r
}\r
\r
- Ip->v4.Addr[1] = (UINT8)StrDecimalToUintn (++Str);\r
-\r
- Str = StrStr (Str, L".");\r
- if (Str == NULL) {\r
- return EFI_INVALID_PARAMETER;\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
- Ip->v4.Addr[2] = (UINT8)StrDecimalToUintn (++Str);\r
-\r
- Str = StrStr (Str, L".");\r
- if (Str == NULL) {\r
- return EFI_INVALID_PARAMETER;\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
+
+ @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
- Ip->v4.Addr[3] = (UINT8)StrDecimalToUintn (++Str);\r
}\r
-\r
- return Status;\r
}\r
\r
EFI_STATUS\r
\r
while(1) {\r
Print (L"[y/n] ");\r
- Status = GetHIInputStr (CmdBoolean, 2);\r
+ Status = GetHIInputStr (CmdBoolean, 2);
if (EFI_ERROR(Status)) {\r
return Status;\r
} else if ((CmdBoolean[0] == L'y') || (CmdBoolean[0] == L'Y')) {\r
IN CHAR16* FilePath\r
)\r
{\r
- return (StrCmp (FilePath + (StrSize(FilePath)/sizeof(CHAR16)) - 5, L".efi") == 0);\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
}\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 2 x BOOT_DEVICE_OPTION_MAX (600 bytes)\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 * 2; 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