]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPlatformPkg/Bds/BdsHelper.c
ArmPlatformPkg/Bds: Change the GetHIInput/EditHIInput to always return a valid IP...
[mirror_edk2.git] / ArmPlatformPkg / Bds / BdsHelper.c
index 3142d85c10cdf46cdecbdd7f155712782f0f6ab3..693bc7d12a1494ae2e87c9581857e88699da6662 100644 (file)
@@ -1,6 +1,6 @@
 /** @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
@@ -12,6 +12,7 @@
 *\r
 **/\r
 \r
+#include <Library/NetLib.h>\r
 #include "BdsInternal.h"\r
 \r
 EFI_STATUS\r
@@ -35,7 +36,7 @@ EditHIInputStr (
   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
@@ -62,7 +63,7 @@ EditHIInputStr (
       }\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
@@ -137,44 +138,99 @@ GetHIInputInteger (
   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
@@ -187,9 +243,7 @@ GetHIInputBoolean (
 \r
   while(1) {\r
     Print (L"[y/n] ");\r
-    // Set MaxCmdLine to 3 to give space for carriage return (when the user\r
-    // hits enter) and terminal '\0'.\r
-    Status = GetHIInputStr (CmdBoolean, 3);\r
+    Status = GetHIInputStr (CmdBoolean, 2);
     if (EFI_ERROR(Status)) {\r
       return Status;\r
     } else if ((CmdBoolean[0] == L'y') || (CmdBoolean[0] == L'Y')) {\r
@@ -325,3 +379,94 @@ GetAlignedDevicePath (
   }\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