]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/BaseLib/SafeString.c
MdePkg/BaseLib: Add StrToGuid/StrHexToBytes/StrToIpv[4/6]Address
[mirror_edk2.git] / MdePkg / Library / BaseLib / SafeString.c
index 34d3efeafc94dabc4faaa3542a4acaf8db20a69e..cf6f3e9eb90a3acfb079d5807306e3d0ef44c8ef 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Safe String functions.\r
 \r
-  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR>\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
 \r
 **/\r
 \r
-#include <Base.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/PcdLib.h>\r
-#include <Library/BaseLib.h>\r
+#include "BaseLibInternals.h"\r
 \r
 #define RSIZE_MAX  (PcdGet32 (PcdMaximumUnicodeStringLength))\r
 \r
@@ -131,9 +128,9 @@ StrnLenS (
   ASSERT (((UINTN) String & BIT0) == 0);\r
 \r
   //\r
-  // If String is a null pointer, then the StrnLenS function returns zero.\r
+  // If String is a null pointer or MaxSize is 0, then the StrnLenS function returns zero.\r
   //\r
-  if (String == NULL) {\r
+  if ((String == NULL) || (MaxSize == 0)) {\r
     return 0;\r
   }\r
 \r
@@ -143,12 +140,61 @@ StrnLenS (
   // String then StrnLenS returns MaxSize. At most the first MaxSize characters of String shall\r
   // be accessed by StrnLenS.\r
   //\r
-  for (Length = 0; (Length < MaxSize) && (*String != 0); String++, Length++) {\r
-    ;\r
+  Length = 0;\r
+  while (String[Length] != 0) {\r
+    if (Length >= MaxSize - 1) {\r
+      return MaxSize;\r
+    }\r
+    Length++;\r
   }\r
   return Length;\r
 }\r
 \r
+/**\r
+  Returns the size of a Null-terminated Unicode string in bytes, including the\r
+  Null terminator.\r
+\r
+  This function returns the size of the Null-terminated Unicode string\r
+  specified by String in bytes, including the Null terminator.\r
+\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  MaxSize  The maximum number of Destination Unicode\r
+                   char, including the Null terminator.\r
+\r
+  @retval 0  If String is NULL.\r
+  @retval (sizeof (CHAR16) * (MaxSize + 1))\r
+             If there is no Null terminator in the first MaxSize characters of\r
+             String.\r
+  @return The size of the Null-terminated Unicode string in bytes, including\r
+          the Null terminator.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+StrnSizeS (\r
+  IN CONST CHAR16              *String,\r
+  IN UINTN                     MaxSize\r
+  )\r
+{\r
+  //\r
+  // If String is a null pointer, then the StrnSizeS function returns zero.\r
+  //\r
+  if (String == NULL) {\r
+    return 0;\r
+  }\r
+\r
+  //\r
+  // Otherwise, the StrnSizeS function returns the size of the Null-terminated\r
+  // Unicode string in bytes, including the Null terminator. If there is no\r
+  // Null terminator in the first MaxSize characters of String, then StrnSizeS\r
+  // returns (sizeof (CHAR16) * (MaxSize + 1)) to keep a consistent map with\r
+  // the StrnLenS function.\r
+  //\r
+  return (StrnLenS (String, MaxSize) + 1) * sizeof (*String);\r
+}\r
+\r
 /**\r
   Copies the string pointed to by Source (including the terminating null char)\r
   to the array pointed to by Destination.\r
@@ -536,355 +582,2316 @@ StrnCatS (
 }\r
 \r
 /**\r
-  Returns the length of a Null-terminated Ascii string.\r
-\r
-  This function is similar as strlen_s defined in C11.\r
-\r
-  @param  String   A pointer to a Null-terminated Ascii string.\r
-  @param  MaxSize  The maximum number of Destination Ascii\r
-                   char, including terminating null char.\r
-\r
-  @retval 0        If String is NULL.\r
-  @retval MaxSize  If there is no null character in the first MaxSize characters of String.\r
-  @return The number of characters that percede the terminating null character.\r
+  Convert a Null-terminated Unicode decimal string to a value of type UINTN.\r
+\r
+  This function outputs a value of type UINTN by interpreting the contents of\r
+  the Unicode string specified by String as a decimal number. The format of the\r
+  input Unicode string String is:\r
+\r
+                  [spaces] [decimal digits].\r
+\r
+  The valid decimal digit character is in the range [0-9]. The function will\r
+  ignore the pad space, which includes spaces or tab characters, before\r
+  [decimal digits]. The running zero in the beginning of [decimal digits] will\r
+  be ignored. Then, the function stops at the first character that is a not a\r
+  valid decimal character or a Null-terminator, whichever one comes first.\r
+\r
+  If String is NULL, then ASSERT().\r
+  If Data is NULL, then ASSERT().\r
+  If String is not aligned in a 16-bit boundary, then ASSERT().\r
+  If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
+  PcdMaximumUnicodeStringLength Unicode characters, not including the\r
+  Null-terminator, then ASSERT().\r
+\r
+  If String has no valid decimal digits in the above format, then 0 is stored\r
+  at the location pointed to by Data.\r
+  If the number represented by String exceeds the range defined by UINTN, then\r
+  MAX_UINTN is stored at the location pointed to by Data.\r
+\r
+  If EndPointer is not NULL, a pointer to the character that stopped the scan\r
+  is stored at the location pointed to by EndPointer. If String has no valid\r
+  decimal digits right after the optional pad spaces, the value of String is\r
+  stored at the location pointed to by EndPointer.\r
+\r
+  @param  String                   Pointer to a Null-terminated Unicode string.\r
+  @param  EndPointer               Pointer to character that stops scan.\r
+  @param  Data                     Pointer to the converted value.\r
+\r
+  @retval RETURN_SUCCESS           Value is translated from String.\r
+  @retval RETURN_INVALID_PARAMETER If String is NULL.\r
+                                   If Data is NULL.\r
+                                   If PcdMaximumUnicodeStringLength is not\r
+                                   zero, and String contains more than\r
+                                   PcdMaximumUnicodeStringLength Unicode\r
+                                   characters, not including the\r
+                                   Null-terminator.\r
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds\r
+                                   the range defined by UINTN.\r
 \r
 **/\r
-UINTN\r
+RETURN_STATUS\r
 EFIAPI\r
-AsciiStrnLenS (\r
-  IN CONST CHAR8               *String,\r
-  IN UINTN                     MaxSize\r
+StrDecimalToUintnS (\r
+  IN  CONST CHAR16             *String,\r
+  OUT       CHAR16             **EndPointer,  OPTIONAL\r
+  OUT       UINTN              *Data\r
   )\r
 {\r
-  UINTN                             Length;\r
+  ASSERT (((UINTN) String & BIT0) == 0);\r
 \r
   //\r
-  // If String is a null pointer, then the AsciiStrnLenS function returns zero.\r
+  // 1. Neither String nor Data shall be a null pointer.\r
   //\r
-  if (String == NULL) {\r
-    return 0;\r
-  }\r
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);\r
 \r
   //\r
-  // Otherwise, the AsciiStrnLenS function returns the number of characters that precede the\r
-  // terminating null character. If there is no null character in the first MaxSize characters of\r
-  // String then AsciiStrnLenS returns MaxSize. At most the first MaxSize characters of String shall\r
-  // be accessed by AsciiStrnLenS.\r
+  // 2. The length of String shall not be greater than RSIZE_MAX.\r
   //\r
-  for (Length = 0; (Length < MaxSize) && (*String != 0); String++, Length++) {\r
-    ;\r
+  if (RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
   }\r
-  return Length;\r
-}\r
 \r
-/**\r
-  Copies the string pointed to by Source (including the terminating null char)\r
-  to the array pointed to by Destination.\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR16 *) String;\r
+  }\r
 \r
-  This function is similar as strcpy_s defined in C11.\r
+  //\r
+  // Ignore the pad spaces (space or tab)\r
+  //\r
+  while ((*String == L' ') || (*String == L'\t')) {\r
+    String++;\r
+  }\r
 \r
-  If an error would be returned, then the function will also ASSERT().\r
+  //\r
+  // Ignore leading Zeros after the spaces\r
+  //\r
+  while (*String == L'0') {\r
+    String++;\r
+  }\r
 \r
-  If an error is returned, then the Destination is unmodified.\r
+  *Data = 0;\r
+\r
+  while (InternalIsDecimalDigitCharacter (*String)) {\r
+    //\r
+    // If the number represented by String overflows according to the range\r
+    // defined by UINTN, then MAX_UINTN is stored in *Data and\r
+    // RETURN_UNSUPPORTED is returned.\r
+    //\r
+    if (*Data > ((MAX_UINTN - (*String - L'0')) / 10)) {\r
+      *Data = MAX_UINTN;\r
+      if (EndPointer != NULL) {\r
+        *EndPointer = (CHAR16 *) String;\r
+      }\r
+      return RETURN_UNSUPPORTED;\r
+    }\r
+\r
+    *Data = *Data * 10 + (*String - L'0');\r
+    String++;\r
+  }\r
 \r
-  @param  Destination              A pointer to a Null-terminated Ascii string.\r
-  @param  DestMax                  The maximum number of Destination Ascii\r
-                                   char, including terminating null char.\r
-  @param  Source                   A pointer to a Null-terminated Ascii string.\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR16 *) String;\r
+  }\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Convert a Null-terminated Unicode decimal string to a value of type UINT64.\r
+\r
+  This function outputs a value of type UINT64 by interpreting the contents of\r
+  the Unicode string specified by String as a decimal number. The format of the\r
+  input Unicode string String is:\r
+\r
+                  [spaces] [decimal digits].\r
+\r
+  The valid decimal digit character is in the range [0-9]. The function will\r
+  ignore the pad space, which includes spaces or tab characters, before\r
+  [decimal digits]. The running zero in the beginning of [decimal digits] will\r
+  be ignored. Then, the function stops at the first character that is a not a\r
+  valid decimal character or a Null-terminator, whichever one comes first.\r
+\r
+  If String is NULL, then ASSERT().\r
+  If Data is NULL, then ASSERT().\r
+  If String is not aligned in a 16-bit boundary, then ASSERT().\r
+  If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
+  PcdMaximumUnicodeStringLength Unicode characters, not including the\r
+  Null-terminator, then ASSERT().\r
+\r
+  If String has no valid decimal digits in the above format, then 0 is stored\r
+  at the location pointed to by Data.\r
+  If the number represented by String exceeds the range defined by UINT64, then\r
+  MAX_UINT64 is stored at the location pointed to by Data.\r
+\r
+  If EndPointer is not NULL, a pointer to the character that stopped the scan\r
+  is stored at the location pointed to by EndPointer. If String has no valid\r
+  decimal digits right after the optional pad spaces, the value of String is\r
+  stored at the location pointed to by EndPointer.\r
+\r
+  @param  String                   Pointer to a Null-terminated Unicode string.\r
+  @param  EndPointer               Pointer to character that stops scan.\r
+  @param  Data                     Pointer to the converted value.\r
+\r
+  @retval RETURN_SUCCESS           Value is translated from String.\r
+  @retval RETURN_INVALID_PARAMETER If String is NULL.\r
+                                   If Data is NULL.\r
+                                   If PcdMaximumUnicodeStringLength is not\r
+                                   zero, and String contains more than\r
+                                   PcdMaximumUnicodeStringLength Unicode\r
+                                   characters, not including the\r
+                                   Null-terminator.\r
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds\r
+                                   the range defined by UINT64.\r
 \r
-  @retval RETURN_SUCCESS           String is copied.\r
-  @retval RETURN_BUFFER_TOO_SMALL  If DestMax is NOT greater than StrLen(Source).\r
-  @retval RETURN_INVALID_PARAMETER If Destination is NULL.\r
-                                   If Source is NULL.\r
-                                   If PcdMaximumAsciiStringLength is not zero,\r
-                                    and DestMax is greater than \r
-                                    PcdMaximumAsciiStringLength.\r
-                                   If DestMax is 0.\r
-  @retval RETURN_ACCESS_DENIED     If Source and Destination overlap.\r
 **/\r
 RETURN_STATUS\r
 EFIAPI\r
-AsciiStrCpyS (\r
-  OUT CHAR8        *Destination,\r
-  IN  UINTN        DestMax,\r
-  IN  CONST CHAR8  *Source\r
+StrDecimalToUint64S (\r
+  IN  CONST CHAR16             *String,\r
+  OUT       CHAR16             **EndPointer,  OPTIONAL\r
+  OUT       UINT64             *Data\r
   )\r
 {\r
-  UINTN            SourceLen;\r
-  \r
+  ASSERT (((UINTN) String & BIT0) == 0);\r
+\r
   //\r
-  // 1. Neither Destination nor Source shall be a null pointer.\r
+  // 1. Neither String nor Data shall be a null pointer.\r
   //\r
-  SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);\r
-  SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);\r
 \r
   //\r
-  // 2. DestMax shall not be greater than ASCII_RSIZE_MAX.\r
+  // 2. The length of String shall not be greater than RSIZE_MAX.\r
   //\r
-  if (ASCII_RSIZE_MAX != 0) {\r
-    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  if (RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
   }\r
 \r
-  //\r
-  // 3. DestMax shall not equal zero.\r
-  //\r
-  SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR16 *) String;\r
+  }\r
 \r
   //\r
-  // 4. DestMax shall be greater than AsciiStrnLenS(Source, DestMax).\r
+  // Ignore the pad spaces (space or tab)\r
   //\r
-  SourceLen = AsciiStrnLenS (Source, DestMax);\r
-  SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);\r
+  while ((*String == L' ') || (*String == L'\t')) {\r
+    String++;\r
+  }\r
 \r
   //\r
-  // 5. Copying shall not take place between objects that overlap.\r
+  // Ignore leading Zeros after the spaces\r
   //\r
-  SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);\r
+  while (*String == L'0') {\r
+    String++;\r
+  }\r
 \r
-  //\r
-  // The AsciiStrCpyS function copies the string pointed to by Source (including the terminating\r
-  // null character) into the array pointed to by Destination.\r
-  //\r
-  while (*Source != 0) {\r
-    *(Destination++) = *(Source++);\r
+  *Data = 0;\r
+\r
+  while (InternalIsDecimalDigitCharacter (*String)) {\r
+    //\r
+    // If the number represented by String overflows according to the range\r
+    // defined by UINT64, then MAX_UINT64 is stored in *Data and\r
+    // RETURN_UNSUPPORTED is returned.\r
+    //\r
+    if (*Data > DivU64x32 (MAX_UINT64 - (*String - L'0'), 10)) {\r
+      *Data = MAX_UINT64;\r
+      if (EndPointer != NULL) {\r
+        *EndPointer = (CHAR16 *) String;\r
+      }\r
+      return RETURN_UNSUPPORTED;\r
+    }\r
+\r
+    *Data = MultU64x32 (*Data, 10) + (*String - L'0');\r
+    String++;\r
   }\r
-  *Destination = 0;\r
 \r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR16 *) String;\r
+  }\r
   return RETURN_SUCCESS;\r
 }\r
 \r
 /**\r
-  Copies not more than Length successive char from the string pointed to by\r
-  Source to the array pointed to by Destination. If no null char is copied from\r
-  Source, then Destination[Length] is always set to null.\r
-\r
-  This function is similar as strncpy_s defined in C11.\r
-\r
-  If an error would be returned, then the function will also ASSERT().\r
-\r
-  If an error is returned, then the Destination is unmodified.\r
-\r
-  @param  Destination              A pointer to a Null-terminated Ascii string.\r
-  @param  DestMax                  The maximum number of Destination Ascii\r
-                                   char, including terminating null char.\r
-  @param  Source                   A pointer to a Null-terminated Ascii string.\r
-  @param  Length                   The maximum number of Ascii characters to copy.\r
+  Convert a Null-terminated Unicode hexadecimal string to a value of type\r
+  UINTN.\r
+\r
+  This function outputs a value of type UINTN by interpreting the contents of\r
+  the Unicode string specified by String as a hexadecimal number. The format of\r
+  the input Unicode string String is:\r
+\r
+                  [spaces][zeros][x][hexadecimal digits].\r
+\r
+  The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
+  The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.\r
+  If "x" appears in the input string, it must be prefixed with at least one 0.\r
+  The function will ignore the pad space, which includes spaces or tab\r
+  characters, before [zeros], [x] or [hexadecimal digit]. The running zero\r
+  before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts\r
+  after [x] or the first valid hexadecimal digit. Then, the function stops at\r
+  the first character that is a not a valid hexadecimal character or NULL,\r
+  whichever one comes first.\r
+\r
+  If String is NULL, then ASSERT().\r
+  If Data is NULL, then ASSERT().\r
+  If String is not aligned in a 16-bit boundary, then ASSERT().\r
+  If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
+  PcdMaximumUnicodeStringLength Unicode characters, not including the\r
+  Null-terminator, then ASSERT().\r
+\r
+  If String has no valid hexadecimal digits in the above format, then 0 is\r
+  stored at the location pointed to by Data.\r
+  If the number represented by String exceeds the range defined by UINTN, then\r
+  MAX_UINTN is stored at the location pointed to by Data.\r
+\r
+  If EndPointer is not NULL, a pointer to the character that stopped the scan\r
+  is stored at the location pointed to by EndPointer. If String has no valid\r
+  hexadecimal digits right after the optional pad spaces, the value of String\r
+  is stored at the location pointed to by EndPointer.\r
+\r
+  @param  String                   Pointer to a Null-terminated Unicode string.\r
+  @param  EndPointer               Pointer to character that stops scan.\r
+  @param  Data                     Pointer to the converted value.\r
+\r
+  @retval RETURN_SUCCESS           Value is translated from String.\r
+  @retval RETURN_INVALID_PARAMETER If String is NULL.\r
+                                   If Data is NULL.\r
+                                   If PcdMaximumUnicodeStringLength is not\r
+                                   zero, and String contains more than\r
+                                   PcdMaximumUnicodeStringLength Unicode\r
+                                   characters, not including the\r
+                                   Null-terminator.\r
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds\r
+                                   the range defined by UINTN.\r
 \r
-  @retval RETURN_SUCCESS           String is copied.\r
-  @retval RETURN_BUFFER_TOO_SMALL  If DestMax is NOT greater than \r
-                                   MIN(StrLen(Source), Length).\r
-  @retval RETURN_INVALID_PARAMETER If Destination is NULL.\r
-                                   If Source is NULL.\r
-                                   If PcdMaximumAsciiStringLength is not zero,\r
-                                    and DestMax is greater than \r
-                                    PcdMaximumAsciiStringLength.\r
-                                   If DestMax is 0.\r
-  @retval RETURN_ACCESS_DENIED     If Source and Destination overlap.\r
 **/\r
 RETURN_STATUS\r
 EFIAPI\r
-AsciiStrnCpyS (\r
-  OUT CHAR8        *Destination,\r
-  IN  UINTN        DestMax,\r
-  IN  CONST CHAR8  *Source,\r
-  IN  UINTN        Length\r
+StrHexToUintnS (\r
+  IN  CONST CHAR16             *String,\r
+  OUT       CHAR16             **EndPointer,  OPTIONAL\r
+  OUT       UINTN              *Data\r
   )\r
 {\r
-  UINTN            SourceLen;\r
+  ASSERT (((UINTN) String & BIT0) == 0);\r
 \r
   //\r
-  // 1. Neither Destination nor Source shall be a null pointer.\r
+  // 1. Neither String nor Data shall be a null pointer.\r
   //\r
-  SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);\r
-  SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);\r
 \r
   //\r
-  // 2. Neither DestMax nor Length shall be greater than ASCII_RSIZE_MAX\r
+  // 2. The length of String shall not be greater than RSIZE_MAX.\r
   //\r
-  if (ASCII_RSIZE_MAX != 0) {\r
-    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
-    SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  if (RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
   }\r
 \r
-  //\r
-  // 3. DestMax shall not equal zero.\r
-  //\r
-  SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR16 *) String;\r
+  }\r
 \r
   //\r
-  // 4. If Length is not less than DestMax, then DestMax shall be greater than AsciiStrnLenS(Source, DestMax).\r
+  // Ignore the pad spaces (space or tab)\r
   //\r
-  SourceLen = AsciiStrnLenS (Source, DestMax);\r
-  if (Length >= DestMax) {\r
-    SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);\r
+  while ((*String == L' ') || (*String == L'\t')) {\r
+    String++;\r
   }\r
 \r
   //\r
-  // 5. Copying shall not take place between objects that overlap.\r
+  // Ignore leading Zeros after the spaces\r
   //\r
-  if (SourceLen > Length) {\r
-    SourceLen = Length;\r
+  while (*String == L'0') {\r
+    String++;\r
   }\r
-  SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);\r
 \r
-  //\r
-  // The AsciiStrnCpyS function copies not more than Length successive characters (characters that\r
-  // follow a null character are not copied) from the array pointed to by Source to the array\r
-  // pointed to by Destination. If no null character was copied from Source, then Destination[Length] is set to a null\r
-  // character.\r
-  //\r
-  while ((*Source != 0) && (SourceLen > 0)) {\r
-    *(Destination++) = *(Source++);\r
-    SourceLen--;\r
+  if (InternalCharToUpper (*String) == L'X') {\r
+    if (*(String - 1) != L'0') {\r
+      *Data = 0;\r
+      return RETURN_SUCCESS;\r
+    }\r
+    //\r
+    // Skip the 'X'\r
+    //\r
+    String++;\r
+  }\r
+\r
+  *Data = 0;\r
+\r
+  while (InternalIsHexaDecimalDigitCharacter (*String)) {\r
+    //\r
+    // If the number represented by String overflows according to the range\r
+    // defined by UINTN, then MAX_UINTN is stored in *Data and\r
+    // RETURN_UNSUPPORTED is returned.\r
+    //\r
+    if (*Data > ((MAX_UINTN - InternalHexCharToUintn (*String)) >> 4)) {\r
+      *Data = MAX_UINTN;\r
+      if (EndPointer != NULL) {\r
+        *EndPointer = (CHAR16 *) String;\r
+      }\r
+      return RETURN_UNSUPPORTED;\r
+    }\r
+\r
+    *Data = (*Data << 4) + InternalHexCharToUintn (*String);\r
+    String++;\r
   }\r
-  *Destination = 0;\r
 \r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR16 *) String;\r
+  }\r
   return RETURN_SUCCESS;\r
 }\r
 \r
 /**\r
-  Appends a copy of the string pointed to by Source (including the terminating\r
-  null char) to the end of the string pointed to by Destination.\r
-\r
-  This function is similar as strcat_s defined in C11.\r
+  Convert a Null-terminated Unicode hexadecimal string to a value of type\r
+  UINT64.\r
+\r
+  This function outputs a value of type UINT64 by interpreting the contents of\r
+  the Unicode string specified by String as a hexadecimal number. The format of\r
+  the input Unicode string String is:\r
+\r
+                  [spaces][zeros][x][hexadecimal digits].\r
+\r
+  The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
+  The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.\r
+  If "x" appears in the input string, it must be prefixed with at least one 0.\r
+  The function will ignore the pad space, which includes spaces or tab\r
+  characters, before [zeros], [x] or [hexadecimal digit]. The running zero\r
+  before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts\r
+  after [x] or the first valid hexadecimal digit. Then, the function stops at\r
+  the first character that is a not a valid hexadecimal character or NULL,\r
+  whichever one comes first.\r
+\r
+  If String is NULL, then ASSERT().\r
+  If Data is NULL, then ASSERT().\r
+  If String is not aligned in a 16-bit boundary, then ASSERT().\r
+  If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
+  PcdMaximumUnicodeStringLength Unicode characters, not including the\r
+  Null-terminator, then ASSERT().\r
+\r
+  If String has no valid hexadecimal digits in the above format, then 0 is\r
+  stored at the location pointed to by Data.\r
+  If the number represented by String exceeds the range defined by UINT64, then\r
+  MAX_UINT64 is stored at the location pointed to by Data.\r
+\r
+  If EndPointer is not NULL, a pointer to the character that stopped the scan\r
+  is stored at the location pointed to by EndPointer. If String has no valid\r
+  hexadecimal digits right after the optional pad spaces, the value of String\r
+  is stored at the location pointed to by EndPointer.\r
+\r
+  @param  String                   Pointer to a Null-terminated Unicode string.\r
+  @param  EndPointer               Pointer to character that stops scan.\r
+  @param  Data                     Pointer to the converted value.\r
+\r
+  @retval RETURN_SUCCESS           Value is translated from String.\r
+  @retval RETURN_INVALID_PARAMETER If String is NULL.\r
+                                   If Data is NULL.\r
+                                   If PcdMaximumUnicodeStringLength is not\r
+                                   zero, and String contains more than\r
+                                   PcdMaximumUnicodeStringLength Unicode\r
+                                   characters, not including the\r
+                                   Null-terminator.\r
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds\r
+                                   the range defined by UINT64.\r
 \r
-  If an error would be returned, then the function will also ASSERT().\r
-\r
-  If an error is returned, then the Destination is unmodified.\r
-\r
-  @param  Destination              A pointer to a Null-terminated Ascii string.\r
-  @param  DestMax                  The maximum number of Destination Ascii\r
-                                   char, including terminating null char.\r
-  @param  Source                   A pointer to a Null-terminated Ascii string.\r
-\r
-  @retval RETURN_SUCCESS           String is appended.\r
-  @retval RETURN_BAD_BUFFER_SIZE   If DestMax is NOT greater than \r
-                                   StrLen(Destination).\r
-  @retval RETURN_BUFFER_TOO_SMALL  If (DestMax - StrLen(Destination)) is NOT\r
-                                   greater than StrLen(Source).\r
-  @retval RETURN_INVALID_PARAMETER If Destination is NULL.\r
-                                   If Source is NULL.\r
-                                   If PcdMaximumAsciiStringLength is not zero,\r
-                                    and DestMax is greater than \r
-                                    PcdMaximumAsciiStringLength.\r
-                                   If DestMax is 0.\r
-  @retval RETURN_ACCESS_DENIED     If Source and Destination overlap.\r
 **/\r
 RETURN_STATUS\r
 EFIAPI\r
-AsciiStrCatS (\r
-  IN OUT CHAR8        *Destination,\r
-  IN     UINTN        DestMax,\r
-  IN     CONST CHAR8  *Source\r
+StrHexToUint64S (\r
+  IN  CONST CHAR16             *String,\r
+  OUT       CHAR16             **EndPointer,  OPTIONAL\r
+  OUT       UINT64             *Data\r
   )\r
 {\r
-  UINTN               DestLen;\r
-  UINTN               CopyLen;\r
-  UINTN               SourceLen;\r
-  \r
-  //\r
-  // Let CopyLen denote the value DestMax - AsciiStrnLenS(Destination, DestMax) upon entry to AsciiStrCatS.\r
-  //\r
-  DestLen = AsciiStrnLenS (Destination, DestMax);\r
-  CopyLen = DestMax - DestLen;\r
+  ASSERT (((UINTN) String & BIT0) == 0);\r
 \r
   //\r
-  // 1. Neither Destination nor Source shall be a null pointer.\r
+  // 1. Neither String nor Data shall be a null pointer.\r
   //\r
-  SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);\r
-  SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);\r
 \r
   //\r
-  // 2. DestMax shall not be greater than ASCII_RSIZE_MAX.\r
+  // 2. The length of String shall not be greater than RSIZE_MAX.\r
   //\r
-  if (ASCII_RSIZE_MAX != 0) {\r
-    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  if (RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
   }\r
 \r
-  //\r
-  // 3. DestMax shall not equal zero.\r
-  //\r
-  SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR16 *) String;\r
+  }\r
 \r
   //\r
-  // 4. CopyLen shall not equal zero.\r
+  // Ignore the pad spaces (space or tab)\r
   //\r
-  SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE);\r
+  while ((*String == L' ') || (*String == L'\t')) {\r
+    String++;\r
+  }\r
 \r
   //\r
-  // 5. CopyLen shall be greater than AsciiStrnLenS(Source, CopyLen).\r
+  // Ignore leading Zeros after the spaces\r
   //\r
-  SourceLen = AsciiStrnLenS (Source, CopyLen);\r
-  SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL);\r
+  while (*String == L'0') {\r
+    String++;\r
+  }\r
 \r
-  //\r
-  // 6. Copying shall not take place between objects that overlap.\r
-  //\r
-  SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);\r
+  if (InternalCharToUpper (*String) == L'X') {\r
+    if (*(String - 1) != L'0') {\r
+      *Data = 0;\r
+      return RETURN_SUCCESS;\r
+    }\r
+    //\r
+    // Skip the 'X'\r
+    //\r
+    String++;\r
+  }\r
 \r
-  //\r
-  // The AsciiStrCatS function appends a copy of the string pointed to by Source (including the\r
-  // terminating null character) to the end of the string pointed to by Destination. The initial character\r
-  // from Source overwrites the null character at the end of Destination.\r
-  //\r
+  *Data = 0;\r
+\r
+  while (InternalIsHexaDecimalDigitCharacter (*String)) {\r
+    //\r
+    // If the number represented by String overflows according to the range\r
+    // defined by UINT64, then MAX_UINT64 is stored in *Data and\r
+    // RETURN_UNSUPPORTED is returned.\r
+    //\r
+    if (*Data > RShiftU64 (MAX_UINT64 - InternalHexCharToUintn (*String), 4)) {\r
+      *Data = MAX_UINT64;\r
+      if (EndPointer != NULL) {\r
+        *EndPointer = (CHAR16 *) String;\r
+      }\r
+      return RETURN_UNSUPPORTED;\r
+    }\r
+\r
+    *Data = LShiftU64 (*Data, 4) + InternalHexCharToUintn (*String);\r
+    String++;\r
+  }\r
+\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR16 *) String;\r
+  }\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Convert a Null-terminated Unicode string to IPv6 address and prefix length.\r
+\r
+  This function outputs a value of type IPv6_ADDRESS and may output a value\r
+  of type UINT8 by interpreting the contents of the Unicode string specified\r
+  by String. The format of the input Unicode string String is as follows:\r
+\r
+                  X:X:X:X:X:X:X:X[/P]\r
+\r
+  X contains one to four hexadecimal digit characters in the range [0-9], [a-f] and\r
+  [A-F]. X is converted to a value of type UINT16, whose low byte is stored in low\r
+  memory address and high byte is stored in high memory address. P contains decimal\r
+  digit characters in the range [0-9]. The running zero in the beginning of P will\r
+  be ignored. /P is optional.\r
+\r
+  When /P is not in the String, the function stops at the first character that is\r
+  not a valid hexadecimal digit character after eight X's are converted.\r
+\r
+  When /P is in the String, the function stops at the first character that is not\r
+  a valid decimal digit character after P is converted.\r
+\r
+  "::" can be used to compress one or more groups of X when X contains only 0.\r
+  The "::" can only appear once in the String.\r
+\r
+  If String is NULL, then ASSERT().\r
+\r
+  If Address is NULL, then ASSERT().\r
+\r
+  If String is not aligned in a 16-bit boundary, then ASSERT().\r
+\r
+  If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
+  PcdMaximumUnicodeStringLength Unicode characters, not including the\r
+  Null-terminator, then ASSERT().\r
+\r
+  If EndPointer is not NULL and Address is translated from String, a pointer\r
+  to the character that stopped the scan is stored at the location pointed to\r
+  by EndPointer.\r
+\r
+  @param  String                   Pointer to a Null-terminated Unicode string.\r
+  @param  EndPointer               Pointer to character that stops scan.\r
+  @param  Address                  Pointer to the converted IPv6 address.\r
+  @param  PrefixLength             Pointer to the converted IPv6 address prefix\r
+                                   length. MAX_UINT8 is returned when /P is\r
+                                   not in the String.\r
+\r
+  @retval RETURN_SUCCESS           Address is translated from String.\r
+  @retval RETURN_INVALID_PARAMETER If String is NULL.\r
+                                   If Data is NULL.\r
+  @retval RETURN_UNSUPPORTED       If X contains more than four hexadecimal\r
+                                    digit characters.\r
+                                   If String contains "::" and number of X\r
+                                    is not less than 8.\r
+                                   If P starts with character that is not a\r
+                                    valid decimal digit character.\r
+                                   If the decimal number converted from P\r
+                                    exceeds 128.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+StrToIpv6Address (\r
+  IN  CONST CHAR16       *String,\r
+  OUT CHAR16             **EndPointer, OPTIONAL\r
+  OUT IPv6_ADDRESS       *Address,\r
+  OUT UINT8              *PrefixLength OPTIONAL\r
+  )\r
+{\r
+  RETURN_STATUS          Status;\r
+  UINTN                  AddressIndex;\r
+  UINTN                  Uintn;\r
+  IPv6_ADDRESS           LocalAddress;\r
+  UINT8                  LocalPrefixLength;\r
+  CONST CHAR16           *Pointer;\r
+  CHAR16                 *End;\r
+  UINTN                  CompressStart;\r
+  BOOLEAN                ExpectPrefix;\r
+\r
+  LocalPrefixLength = MAX_UINT8;\r
+  CompressStart     = ARRAY_SIZE (Address->Addr);\r
+  ExpectPrefix      = FALSE;\r
+\r
+  ASSERT (((UINTN) String & BIT0) == 0);\r
+\r
+  //\r
+  // 1. None of String or Guid shall be a null pointer.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+  for (Pointer = String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) {\r
+    if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {\r
+      if (*Pointer != L':') {\r
+        //\r
+        // ":" or "/" should be followed by digit characters.\r
+        //\r
+        return RETURN_UNSUPPORTED;\r
+      }\r
+\r
+      //\r
+      // Meet second ":" after previous ":" or "/"\r
+      // or meet first ":" in the beginning of String.\r
+      //\r
+      if (ExpectPrefix) {\r
+        //\r
+        // ":" shall not be after "/"\r
+        //\r
+        return RETURN_UNSUPPORTED;\r
+      }\r
+\r
+      if (CompressStart != ARRAY_SIZE (Address->Addr) || AddressIndex == ARRAY_SIZE (Address->Addr)) {\r
+        //\r
+        // "::" can only appear once.\r
+        // "::" can only appear when address is not full length.\r
+        //\r
+        return RETURN_UNSUPPORTED;\r
+      } else {\r
+        //\r
+        // Remember the start of zero compressing.\r
+        //\r
+        CompressStart = AddressIndex;\r
+        Pointer++;\r
+\r
+        if (CompressStart == 0) {\r
+          if (*Pointer != L':') {\r
+            //\r
+            // Single ":" shall not be in the beginning of String.\r
+            //\r
+            return RETURN_UNSUPPORTED;\r
+          }\r
+          Pointer++;\r
+        }\r
+      }\r
+    }\r
+\r
+    if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {\r
+      if (*Pointer == L'/') {\r
+        //\r
+        // Might be optional "/P" after "::".\r
+        //\r
+        if (CompressStart != AddressIndex) {\r
+          return RETURN_UNSUPPORTED;\r
+        }\r
+      } else {\r
+        break;\r
+      }\r
+    } else {\r
+      if (!ExpectPrefix) {\r
+        //\r
+        // Get X.\r
+        //\r
+        Status = StrHexToUintnS (Pointer, &End, &Uintn);\r
+        if (RETURN_ERROR (Status) || End - Pointer > 4) {\r
+          //\r
+          // Number of hexadecimal digit characters is no more than 4.\r
+          //\r
+          return RETURN_UNSUPPORTED;\r
+        }\r
+        Pointer = End;\r
+        //\r
+        // Uintn won't exceed MAX_UINT16 if number of hexadecimal digit characters is no more than 4.\r
+        //\r
+        LocalAddress.Addr[AddressIndex] = (UINT8) ((UINT16) Uintn >> 8);\r
+        LocalAddress.Addr[AddressIndex + 1] = (UINT8) Uintn;\r
+        AddressIndex += 2;\r
+      } else {\r
+        //\r
+        // Get P, then exit the loop.\r
+        //\r
+        Status = StrDecimalToUintnS (Pointer, &End, &Uintn);\r
+        if (RETURN_ERROR (Status) || End == Pointer || Uintn > 128) {\r
+          //\r
+          // Prefix length should not exceed 128.\r
+          //\r
+          return RETURN_UNSUPPORTED;\r
+        }\r
+        LocalPrefixLength = (UINT8) Uintn;\r
+        Pointer = End;\r
+        break;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Skip ':' or "/"\r
+    //\r
+    if (*Pointer == L'/') {\r
+      ExpectPrefix = TRUE;\r
+    } else if (*Pointer == L':') {\r
+      if (AddressIndex == ARRAY_SIZE (Address->Addr)) {\r
+        //\r
+        // Meet additional ":" after all 8 16-bit address\r
+        //\r
+        break;\r
+      }\r
+    } else {\r
+      //\r
+      // Meet other character that is not "/" or ":" after all 8 16-bit address\r
+      //\r
+      break;\r
+    }\r
+    Pointer++;\r
+  }\r
+\r
+  if ((AddressIndex == ARRAY_SIZE (Address->Addr) && CompressStart != ARRAY_SIZE (Address->Addr)) ||\r
+    (AddressIndex != ARRAY_SIZE (Address->Addr) && CompressStart == ARRAY_SIZE (Address->Addr))\r
+      ) {\r
+    //\r
+    // Full length of address shall not have compressing zeros.\r
+    // Non-full length of address shall have compressing zeros.\r
+    //\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+  CopyMem (&Address->Addr[0], &LocalAddress.Addr[0], CompressStart);\r
+  ZeroMem (&Address->Addr[CompressStart], ARRAY_SIZE (Address->Addr) - AddressIndex);\r
+  CopyMem (\r
+    &Address->Addr[CompressStart + ARRAY_SIZE (Address->Addr) - AddressIndex],\r
+    &LocalAddress.Addr[CompressStart],\r
+    AddressIndex - CompressStart\r
+    );\r
+\r
+  if (PrefixLength != NULL) {\r
+    *PrefixLength = LocalPrefixLength;\r
+  }\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR16 *) Pointer;\r
+  }\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Convert a Null-terminated Unicode string to IPv4 address and prefix length.\r
+\r
+  This function outputs a value of type IPv4_ADDRESS and may output a value\r
+  of type UINT8 by interpreting the contents of the Unicode string specified\r
+  by String. The format of the input Unicode string String is as follows:\r
+\r
+                  D.D.D.D[/P]\r
+\r
+  D and P are decimal digit characters in the range [0-9]. The running zero in\r
+  the beginning of D and P will be ignored. /P is optional.\r
+\r
+  When /P is not in the String, the function stops at the first character that is\r
+  not a valid decimal digit character after four D's are converted.\r
+\r
+  When /P is in the String, the function stops at the first character that is not\r
+  a valid decimal digit character after P is converted.\r
+\r
+  If String is NULL, then ASSERT().\r
+\r
+  If Address is NULL, then ASSERT().\r
+\r
+  If String is not aligned in a 16-bit boundary, then ASSERT().\r
+\r
+  If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
+  PcdMaximumUnicodeStringLength Unicode characters, not including the\r
+  Null-terminator, then ASSERT().\r
+\r
+  If EndPointer is not NULL and Address is translated from String, a pointer\r
+  to the character that stopped the scan is stored at the location pointed to\r
+  by EndPointer.\r
+\r
+  @param  String                   Pointer to a Null-terminated Unicode string.\r
+  @param  EndPointer               Pointer to character that stops scan.\r
+  @param  Address                  Pointer to the converted IPv4 address.\r
+  @param  PrefixLength             Pointer to the converted IPv4 address prefix\r
+                                   length. MAX_UINT8 is returned when /P is\r
+                                   not in the String.\r
+\r
+  @retval RETURN_SUCCESS           Address is translated from String.\r
+  @retval RETURN_INVALID_PARAMETER If String is NULL.\r
+                                   If Data is NULL.\r
+  @retval RETURN_UNSUPPORTED       If String is not in the correct format.\r
+                                   If any decimal number converted from D\r
+                                    exceeds 255.\r
+                                   If the decimal number converted from P\r
+                                    exceeds 32.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+StrToIpv4Address (\r
+  IN  CONST CHAR16       *String,\r
+  OUT CHAR16             **EndPointer, OPTIONAL\r
+  OUT IPv4_ADDRESS       *Address,\r
+  OUT UINT8              *PrefixLength OPTIONAL\r
+  )\r
+{\r
+  RETURN_STATUS          Status;\r
+  UINTN                  AddressIndex;\r
+  UINTN                  Uintn;\r
+  IPv4_ADDRESS           LocalAddress;\r
+  UINT8                  LocalPrefixLength;\r
+  CHAR16                 *Pointer;\r
+\r
+  LocalPrefixLength = MAX_UINT8;\r
+\r
+  ASSERT (((UINTN) String & BIT0) == 0);\r
+\r
+  //\r
+  // 1. None of String or Guid shall be a null pointer.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+  for (Pointer = (CHAR16 *) String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) {\r
+    if (!InternalIsDecimalDigitCharacter (*Pointer)) {\r
+      //\r
+      // D or P contains invalid characters.\r
+      //\r
+      break;\r
+    }\r
+\r
+    //\r
+    // Get D or P.\r
+    //\r
+    Status = StrDecimalToUintnS ((CONST CHAR16 *) Pointer, &Pointer, &Uintn);\r
+    if (RETURN_ERROR (Status)) {\r
+      return RETURN_UNSUPPORTED;\r
+    }\r
+    if (AddressIndex == ARRAY_SIZE (Address->Addr)) {\r
+      //\r
+      // It's P.\r
+      //\r
+      if (Uintn > 32) {\r
+        return RETURN_UNSUPPORTED;\r
+      }\r
+      LocalPrefixLength = (UINT8) Uintn;\r
+    } else {\r
+      //\r
+      // It's D.\r
+      //\r
+      if (Uintn > MAX_UINT8) {\r
+        return RETURN_UNSUPPORTED;\r
+      }\r
+      LocalAddress.Addr[AddressIndex] = (UINT8) Uintn;\r
+      AddressIndex++;\r
+    }\r
+\r
+    //\r
+    // Check the '.' or '/', depending on the AddressIndex.\r
+    //\r
+    if (AddressIndex == ARRAY_SIZE (Address->Addr)) {\r
+      if (*Pointer == L'/') {\r
+        //\r
+        // '/P' is in the String.\r
+        // Skip "/" and get P in next loop.\r
+        //\r
+        Pointer++;\r
+      } else {\r
+        //\r
+        // '/P' is not in the String.\r
+        //\r
+        break;\r
+      }\r
+    } else if (AddressIndex < ARRAY_SIZE (Address->Addr)) {\r
+      if (*Pointer == L'.') {\r
+        //\r
+        // D should be followed by '.'\r
+        //\r
+        Pointer++;\r
+      } else {\r
+        return RETURN_UNSUPPORTED;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (AddressIndex < ARRAY_SIZE (Address->Addr)) {\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+\r
+  CopyMem (Address, &LocalAddress, sizeof (*Address));\r
+  if (PrefixLength != NULL) {\r
+    *PrefixLength = LocalPrefixLength;\r
+  }\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = Pointer;\r
+  }\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Convert a Null-terminated Unicode GUID string to a value of type\r
+  EFI_GUID.\r
+\r
+  This function outputs a GUID value by interpreting the contents of\r
+  the Unicode string specified by String. The format of the input\r
+  Unicode string String consists of 36 characters, as follows:\r
+\r
+                  aabbccdd-eeff-gghh-iijj-kkllmmnnoopp\r
+\r
+  The pairs aa - pp are two characters in the range [0-9], [a-f] and\r
+  [A-F], with each pair representing a single byte hexadecimal value.\r
+\r
+  The mapping between String and the EFI_GUID structure is as follows:\r
+                  aa          Data1[24:31]\r
+                  bb          Data1[16:23]\r
+                  cc          Data1[8:15]\r
+                  dd          Data1[0:7]\r
+                  ee          Data2[8:15]\r
+                  ff          Data2[0:7]\r
+                  gg          Data3[8:15]\r
+                  hh          Data3[0:7]\r
+                  ii          Data4[0:7]\r
+                  jj          Data4[8:15]\r
+                  kk          Data4[16:23]\r
+                  ll          Data4[24:31]\r
+                  mm          Data4[32:39]\r
+                  nn          Data4[40:47]\r
+                  oo          Data4[48:55]\r
+                  pp          Data4[56:63]\r
+\r
+  If String is NULL, then ASSERT().\r
+  If Guid is NULL, then ASSERT().\r
+  If String is not aligned in a 16-bit boundary, then ASSERT().\r
+\r
+  @param  String                   Pointer to a Null-terminated Unicode string.\r
+  @param  Guid                     Pointer to the converted GUID.\r
+\r
+  @retval RETURN_SUCCESS           Guid is translated from String.\r
+  @retval RETURN_INVALID_PARAMETER If String is NULL.\r
+                                   If Data is NULL.\r
+  @retval RETURN_UNSUPPORTED       If String is not as the above format.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+StrToGuid (\r
+  IN  CONST CHAR16       *String,\r
+  OUT GUID               *Guid\r
+  )\r
+{\r
+  RETURN_STATUS          Status;\r
+  GUID                   LocalGuid;\r
+\r
+  ASSERT (((UINTN) String & BIT0) == 0);\r
+\r
+  //\r
+  // 1. None of String or Guid shall be a null pointer.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Guid != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // Get aabbccdd in big-endian.\r
+  //\r
+  Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data1), (UINT8 *) &LocalGuid.Data1, sizeof (LocalGuid.Data1));\r
+  if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data1)] != L'-') {\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+  //\r
+  // Convert big-endian to little-endian.\r
+  //\r
+  LocalGuid.Data1 = SwapBytes32 (LocalGuid.Data1);\r
+  String += 2 * sizeof (LocalGuid.Data1) + 1;\r
+\r
+  //\r
+  // Get eeff in big-endian.\r
+  //\r
+  Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data2), (UINT8 *) &LocalGuid.Data2, sizeof (LocalGuid.Data2));\r
+  if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data2)] != L'-') {\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+  //\r
+  // Convert big-endian to little-endian.\r
+  //\r
+  LocalGuid.Data2 = SwapBytes16 (LocalGuid.Data2);\r
+  String += 2 * sizeof (LocalGuid.Data2) + 1;\r
+\r
+  //\r
+  // Get gghh in big-endian.\r
+  //\r
+  Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data3), (UINT8 *) &LocalGuid.Data3, sizeof (LocalGuid.Data3));\r
+  if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data3)] != L'-') {\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+  //\r
+  // Convert big-endian to little-endian.\r
+  //\r
+  LocalGuid.Data3 = SwapBytes16 (LocalGuid.Data3);\r
+  String += 2 * sizeof (LocalGuid.Data3) + 1;\r
+\r
+  //\r
+  // Get iijj.\r
+  //\r
+  Status = StrHexToBytes (String, 2 * 2, &LocalGuid.Data4[0], 2);\r
+  if (RETURN_ERROR (Status) || String[2 * 2] != L'-') {\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+  String += 2 * 2 + 1;\r
+\r
+  //\r
+  // Get kkllmmnnoopp.\r
+  //\r
+  Status = StrHexToBytes (String, 2 * 6, &LocalGuid.Data4[2], 6);\r
+  if (RETURN_ERROR (Status)) {\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+\r
+  CopyGuid (Guid, &LocalGuid);\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Convert a Null-terminated Unicode hexadecimal string to a byte array.\r
+\r
+  This function outputs a byte array by interpreting the contents of\r
+  the Unicode string specified by String in hexadecimal format. The format of\r
+  the input Unicode string String is:\r
+\r
+                  [XX]*\r
+\r
+  X is a hexadecimal digit character in the range [0-9], [a-f] and [A-F].\r
+  The function decodes every two hexadecimal digit characters as one byte. The\r
+  decoding stops after Length of characters and outputs Buffer containing\r
+  (Length / 2) bytes.\r
+\r
+  If String is not aligned in a 16-bit boundary, then ASSERT().\r
+\r
+  If String is NULL, then ASSERT().\r
+\r
+  If Buffer is NULL, then ASSERT().\r
+\r
+  If Length is not multiple of 2, then ASSERT().\r
+\r
+  If PcdMaximumUnicodeStringLength is not zero and Length is greater than\r
+  PcdMaximumUnicodeStringLength, then ASSERT().\r
+\r
+  If MaxBufferSize is less than (Length / 2), then ASSERT().\r
+\r
+  @param  String                   Pointer to a Null-terminated Unicode string.\r
+  @param  Length                   The number of Unicode characters to decode.\r
+  @param  Buffer                   Pointer to the converted bytes array.\r
+  @param  MaxBufferSize            The maximum size of Buffer.\r
+\r
+  @retval RETURN_SUCCESS           Buffer is translated from String.\r
+  @retval RETURN_INVALID_PARAMETER If String is NULL.\r
+                                   If Data is NULL.\r
+                                   If Length is not multiple of 2.\r
+                                   If PcdMaximumUnicodeStringLength is not zero,\r
+                                    and Length is greater than\r
+                                    PcdMaximumUnicodeStringLength.\r
+  @retval RETURN_UNSUPPORTED       If Length of characters from String contain\r
+                                    a character that is not valid hexadecimal\r
+                                    digit characters, or a Null-terminator.\r
+  @retval RETURN_BUFFER_TOO_SMALL  If MaxBufferSize is less than (Length / 2).\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+StrHexToBytes (\r
+  IN  CONST CHAR16       *String,\r
+  IN  UINTN              Length,\r
+  OUT UINT8              *Buffer,\r
+  IN  UINTN              MaxBufferSize\r
+  )\r
+{\r
+  UINTN                  Index;\r
+\r
+  ASSERT (((UINTN) String & BIT0) == 0);\r
+\r
+  //\r
+  // 1. None of String or Buffer shall be a null pointer.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Buffer != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 2. Length shall not be greater than RSIZE_MAX.\r
+  //\r
+  if (RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  //\r
+  // 3. Length shall not be odd.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK (((Length & BIT0) == 0), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 4. MaxBufferSize shall equal to or greater than Length / 2.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((MaxBufferSize >= Length / 2), RETURN_BUFFER_TOO_SMALL);\r
+\r
+  //\r
+  // 5. String shall not contains invalid hexadecimal digits.\r
+  //\r
+  for (Index = 0; Index < Length; Index++) {\r
+    if (!InternalIsHexaDecimalDigitCharacter (String[Index])) {\r
+      break;\r
+    }\r
+  }\r
+  if (Index != Length) {\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Convert the hex string to bytes.\r
+  //\r
+  for(Index = 0; Index < Length; Index++) {\r
+\r
+    //\r
+    // For even characters, write the upper nibble for each buffer byte,\r
+    // and for even characters, the lower nibble.\r
+    //\r
+    if ((Index & BIT0) == 0) {\r
+      Buffer[Index / 2]  = (UINT8) InternalHexCharToUintn (String[Index]) << 4;\r
+    } else {\r
+      Buffer[Index / 2] |= (UINT8) InternalHexCharToUintn (String[Index]);\r
+    }\r
+  }\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Returns the length of a Null-terminated Ascii string.\r
+\r
+  This function is similar as strlen_s defined in C11.\r
+\r
+  @param  String   A pointer to a Null-terminated Ascii string.\r
+  @param  MaxSize  The maximum number of Destination Ascii\r
+                   char, including terminating null char.\r
+\r
+  @retval 0        If String is NULL.\r
+  @retval MaxSize  If there is no null character in the first MaxSize characters of String.\r
+  @return The number of characters that percede the terminating null character.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+AsciiStrnLenS (\r
+  IN CONST CHAR8               *String,\r
+  IN UINTN                     MaxSize\r
+  )\r
+{\r
+  UINTN                             Length;\r
+\r
+  //\r
+  // If String is a null pointer or MaxSize is 0, then the AsciiStrnLenS function returns zero.\r
+  //\r
+  if ((String == NULL) || (MaxSize == 0)) {\r
+    return 0;\r
+  }\r
+\r
+  //\r
+  // Otherwise, the AsciiStrnLenS function returns the number of characters that precede the\r
+  // terminating null character. If there is no null character in the first MaxSize characters of\r
+  // String then AsciiStrnLenS returns MaxSize. At most the first MaxSize characters of String shall\r
+  // be accessed by AsciiStrnLenS.\r
+  //\r
+  Length = 0;\r
+  while (String[Length] != 0) {\r
+    if (Length >= MaxSize - 1) {\r
+      return MaxSize;\r
+    }\r
+    Length++;\r
+  }\r
+  return Length;\r
+}\r
+\r
+/**\r
+  Returns the size of a Null-terminated Ascii string in bytes, including the\r
+  Null terminator.\r
+\r
+  This function returns the size of the Null-terminated Ascii string specified\r
+  by String in bytes, including the Null terminator.\r
+\r
+  @param  String   A pointer to a Null-terminated Ascii string.\r
+  @param  MaxSize  The maximum number of Destination Ascii\r
+                   char, including the Null terminator.\r
+\r
+  @retval 0  If String is NULL.\r
+  @retval (sizeof (CHAR8) * (MaxSize + 1))\r
+             If there is no Null terminator in the first MaxSize characters of\r
+             String.\r
+  @return The size of the Null-terminated Ascii string in bytes, including the\r
+          Null terminator.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+AsciiStrnSizeS (\r
+  IN CONST CHAR8               *String,\r
+  IN UINTN                     MaxSize\r
+  )\r
+{\r
+  //\r
+  // If String is a null pointer, then the AsciiStrnSizeS function returns\r
+  // zero.\r
+  //\r
+  if (String == NULL) {\r
+    return 0;\r
+  }\r
+\r
+  //\r
+  // Otherwise, the AsciiStrnSizeS function returns the size of the\r
+  // Null-terminated Ascii string in bytes, including the Null terminator. If\r
+  // there is no Null terminator in the first MaxSize characters of String,\r
+  // then AsciiStrnSizeS returns (sizeof (CHAR8) * (MaxSize + 1)) to keep a\r
+  // consistent map with the AsciiStrnLenS function.\r
+  //\r
+  return (AsciiStrnLenS (String, MaxSize) + 1) * sizeof (*String);\r
+}\r
+\r
+/**\r
+  Copies the string pointed to by Source (including the terminating null char)\r
+  to the array pointed to by Destination.\r
+\r
+  This function is similar as strcpy_s defined in C11.\r
+\r
+  If an error would be returned, then the function will also ASSERT().\r
+\r
+  If an error is returned, then the Destination is unmodified.\r
+\r
+  @param  Destination              A pointer to a Null-terminated Ascii string.\r
+  @param  DestMax                  The maximum number of Destination Ascii\r
+                                   char, including terminating null char.\r
+  @param  Source                   A pointer to a Null-terminated Ascii string.\r
+\r
+  @retval RETURN_SUCCESS           String is copied.\r
+  @retval RETURN_BUFFER_TOO_SMALL  If DestMax is NOT greater than StrLen(Source).\r
+  @retval RETURN_INVALID_PARAMETER If Destination is NULL.\r
+                                   If Source is NULL.\r
+                                   If PcdMaximumAsciiStringLength is not zero,\r
+                                    and DestMax is greater than \r
+                                    PcdMaximumAsciiStringLength.\r
+                                   If DestMax is 0.\r
+  @retval RETURN_ACCESS_DENIED     If Source and Destination overlap.\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+AsciiStrCpyS (\r
+  OUT CHAR8        *Destination,\r
+  IN  UINTN        DestMax,\r
+  IN  CONST CHAR8  *Source\r
+  )\r
+{\r
+  UINTN            SourceLen;\r
+  \r
+  //\r
+  // 1. Neither Destination nor Source shall be a null pointer.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 2. DestMax shall not be greater than ASCII_RSIZE_MAX.\r
+  //\r
+  if (ASCII_RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  //\r
+  // 3. DestMax shall not equal zero.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 4. DestMax shall be greater than AsciiStrnLenS(Source, DestMax).\r
+  //\r
+  SourceLen = AsciiStrnLenS (Source, DestMax);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);\r
+\r
+  //\r
+  // 5. Copying shall not take place between objects that overlap.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);\r
+\r
+  //\r
+  // The AsciiStrCpyS function copies the string pointed to by Source (including the terminating\r
+  // null character) into the array pointed to by Destination.\r
+  //\r
+  while (*Source != 0) {\r
+    *(Destination++) = *(Source++);\r
+  }\r
+  *Destination = 0;\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Copies not more than Length successive char from the string pointed to by\r
+  Source to the array pointed to by Destination. If no null char is copied from\r
+  Source, then Destination[Length] is always set to null.\r
+\r
+  This function is similar as strncpy_s defined in C11.\r
+\r
+  If an error would be returned, then the function will also ASSERT().\r
+\r
+  If an error is returned, then the Destination is unmodified.\r
+\r
+  @param  Destination              A pointer to a Null-terminated Ascii string.\r
+  @param  DestMax                  The maximum number of Destination Ascii\r
+                                   char, including terminating null char.\r
+  @param  Source                   A pointer to a Null-terminated Ascii string.\r
+  @param  Length                   The maximum number of Ascii characters to copy.\r
+\r
+  @retval RETURN_SUCCESS           String is copied.\r
+  @retval RETURN_BUFFER_TOO_SMALL  If DestMax is NOT greater than \r
+                                   MIN(StrLen(Source), Length).\r
+  @retval RETURN_INVALID_PARAMETER If Destination is NULL.\r
+                                   If Source is NULL.\r
+                                   If PcdMaximumAsciiStringLength is not zero,\r
+                                    and DestMax is greater than \r
+                                    PcdMaximumAsciiStringLength.\r
+                                   If DestMax is 0.\r
+  @retval RETURN_ACCESS_DENIED     If Source and Destination overlap.\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+AsciiStrnCpyS (\r
+  OUT CHAR8        *Destination,\r
+  IN  UINTN        DestMax,\r
+  IN  CONST CHAR8  *Source,\r
+  IN  UINTN        Length\r
+  )\r
+{\r
+  UINTN            SourceLen;\r
+\r
+  //\r
+  // 1. Neither Destination nor Source shall be a null pointer.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 2. Neither DestMax nor Length shall be greater than ASCII_RSIZE_MAX\r
+  //\r
+  if (ASCII_RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+    SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  //\r
+  // 3. DestMax shall not equal zero.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 4. If Length is not less than DestMax, then DestMax shall be greater than AsciiStrnLenS(Source, DestMax).\r
+  //\r
+  SourceLen = AsciiStrnLenS (Source, DestMax);\r
+  if (Length >= DestMax) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);\r
+  }\r
+\r
+  //\r
+  // 5. Copying shall not take place between objects that overlap.\r
+  //\r
+  if (SourceLen > Length) {\r
+    SourceLen = Length;\r
+  }\r
+  SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);\r
+\r
+  //\r
+  // The AsciiStrnCpyS function copies not more than Length successive characters (characters that\r
+  // follow a null character are not copied) from the array pointed to by Source to the array\r
+  // pointed to by Destination. If no null character was copied from Source, then Destination[Length] is set to a null\r
+  // character.\r
+  //\r
+  while ((*Source != 0) && (SourceLen > 0)) {\r
+    *(Destination++) = *(Source++);\r
+    SourceLen--;\r
+  }\r
+  *Destination = 0;\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Appends a copy of the string pointed to by Source (including the terminating\r
+  null char) to the end of the string pointed to by Destination.\r
+\r
+  This function is similar as strcat_s defined in C11.\r
+\r
+  If an error would be returned, then the function will also ASSERT().\r
+\r
+  If an error is returned, then the Destination is unmodified.\r
+\r
+  @param  Destination              A pointer to a Null-terminated Ascii string.\r
+  @param  DestMax                  The maximum number of Destination Ascii\r
+                                   char, including terminating null char.\r
+  @param  Source                   A pointer to a Null-terminated Ascii string.\r
+\r
+  @retval RETURN_SUCCESS           String is appended.\r
+  @retval RETURN_BAD_BUFFER_SIZE   If DestMax is NOT greater than \r
+                                   StrLen(Destination).\r
+  @retval RETURN_BUFFER_TOO_SMALL  If (DestMax - StrLen(Destination)) is NOT\r
+                                   greater than StrLen(Source).\r
+  @retval RETURN_INVALID_PARAMETER If Destination is NULL.\r
+                                   If Source is NULL.\r
+                                   If PcdMaximumAsciiStringLength is not zero,\r
+                                    and DestMax is greater than \r
+                                    PcdMaximumAsciiStringLength.\r
+                                   If DestMax is 0.\r
+  @retval RETURN_ACCESS_DENIED     If Source and Destination overlap.\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+AsciiStrCatS (\r
+  IN OUT CHAR8        *Destination,\r
+  IN     UINTN        DestMax,\r
+  IN     CONST CHAR8  *Source\r
+  )\r
+{\r
+  UINTN               DestLen;\r
+  UINTN               CopyLen;\r
+  UINTN               SourceLen;\r
+  \r
+  //\r
+  // Let CopyLen denote the value DestMax - AsciiStrnLenS(Destination, DestMax) upon entry to AsciiStrCatS.\r
+  //\r
+  DestLen = AsciiStrnLenS (Destination, DestMax);\r
+  CopyLen = DestMax - DestLen;\r
+\r
+  //\r
+  // 1. Neither Destination nor Source shall be a null pointer.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 2. DestMax shall not be greater than ASCII_RSIZE_MAX.\r
+  //\r
+  if (ASCII_RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  //\r
+  // 3. DestMax shall not equal zero.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 4. CopyLen shall not equal zero.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE);\r
+\r
+  //\r
+  // 5. CopyLen shall be greater than AsciiStrnLenS(Source, CopyLen).\r
+  //\r
+  SourceLen = AsciiStrnLenS (Source, CopyLen);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL);\r
+\r
+  //\r
+  // 6. Copying shall not take place between objects that overlap.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);\r
+\r
+  //\r
+  // The AsciiStrCatS function appends a copy of the string pointed to by Source (including the\r
+  // terminating null character) to the end of the string pointed to by Destination. The initial character\r
+  // from Source overwrites the null character at the end of Destination.\r
+  //\r
   Destination = Destination + DestLen;\r
   while (*Source != 0) {\r
     *(Destination++) = *(Source++);\r
   }\r
-  *Destination = 0;\r
+  *Destination = 0;\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Appends not more than Length successive char from the string pointed to by\r
+  Source to the end of the string pointed to by Destination. If no null char is\r
+  copied from Source, then Destination[StrLen(Destination) + Length] is always\r
+  set to null.\r
+\r
+  This function is similar as strncat_s defined in C11.\r
+\r
+  If an error would be returned, then the function will also ASSERT().\r
+\r
+  If an error is returned, then the Destination is unmodified.\r
+\r
+  @param  Destination              A pointer to a Null-terminated Ascii string.\r
+  @param  DestMax                  The maximum number of Destination Ascii\r
+                                   char, including terminating null char.\r
+  @param  Source                   A pointer to a Null-terminated Ascii string.\r
+  @param  Length                   The maximum number of Ascii characters to copy.\r
+\r
+  @retval RETURN_SUCCESS           String is appended.\r
+  @retval RETURN_BAD_BUFFER_SIZE   If DestMax is NOT greater than\r
+                                   StrLen(Destination).\r
+  @retval RETURN_BUFFER_TOO_SMALL  If (DestMax - StrLen(Destination)) is NOT\r
+                                   greater than MIN(StrLen(Source), Length).\r
+  @retval RETURN_INVALID_PARAMETER If Destination is NULL.\r
+                                   If Source is NULL.\r
+                                   If PcdMaximumAsciiStringLength is not zero,\r
+                                    and DestMax is greater than \r
+                                    PcdMaximumAsciiStringLength.\r
+                                   If DestMax is 0.\r
+  @retval RETURN_ACCESS_DENIED     If Source and Destination overlap.\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+AsciiStrnCatS (\r
+  IN OUT CHAR8        *Destination,\r
+  IN     UINTN        DestMax,\r
+  IN     CONST CHAR8  *Source,\r
+  IN     UINTN        Length\r
+  )\r
+{\r
+  UINTN               DestLen;\r
+  UINTN               CopyLen;\r
+  UINTN               SourceLen;\r
+  \r
+  //\r
+  // Let CopyLen denote the value DestMax - AsciiStrnLenS(Destination, DestMax) upon entry to AsciiStrnCatS.\r
+  //\r
+  DestLen = AsciiStrnLenS (Destination, DestMax);\r
+  CopyLen = DestMax - DestLen;\r
+\r
+  //\r
+  // 1. Neither Destination nor Source shall be a null pointer.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 2. Neither DestMax nor Length shall be greater than ASCII_RSIZE_MAX.\r
+  //\r
+  if (ASCII_RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+    SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  //\r
+  // 3. DestMax shall not equal zero.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 4. CopyLen shall not equal zero.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE);\r
+\r
+  //\r
+  // 5. If Length is not less than CopyLen, then CopyLen shall be greater than AsciiStrnLenS(Source, CopyLen).\r
+  //\r
+  SourceLen = AsciiStrnLenS (Source, CopyLen);\r
+  if (Length >= CopyLen) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL);\r
+  }\r
+\r
+  //\r
+  // 6. Copying shall not take place between objects that overlap.\r
+  //\r
+  if (SourceLen > Length) {\r
+    SourceLen = Length;\r
+  }\r
+  SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);\r
+\r
+  //\r
+  // The AsciiStrnCatS function appends not more than Length successive characters (characters\r
+  // that follow a null character are not copied) from the array pointed to by Source to the end of\r
+  // the string pointed to by Destination. The initial character from Source overwrites the null character at\r
+  // the end of Destination. If no null character was copied from Source, then Destination[DestMax-CopyLen+Length] is set to\r
+  // a null character.\r
+  //\r
+  Destination = Destination + DestLen;\r
+  while ((*Source != 0) && (SourceLen > 0)) {\r
+    *(Destination++) = *(Source++);\r
+    SourceLen--;\r
+  }\r
+  *Destination = 0;\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Convert a Null-terminated Ascii decimal string to a value of type UINTN.\r
+\r
+  This function outputs a value of type UINTN by interpreting the contents of\r
+  the Ascii string specified by String as a decimal number. The format of the\r
+  input Ascii string String is:\r
+\r
+                  [spaces] [decimal digits].\r
+\r
+  The valid decimal digit character is in the range [0-9]. The function will\r
+  ignore the pad space, which includes spaces or tab characters, before\r
+  [decimal digits]. The running zero in the beginning of [decimal digits] will\r
+  be ignored. Then, the function stops at the first character that is a not a\r
+  valid decimal character or a Null-terminator, whichever one comes first.\r
+\r
+  If String is NULL, then ASSERT().\r
+  If Data is NULL, then ASSERT().\r
+  If PcdMaximumAsciiStringLength is not zero, and String contains more than\r
+  PcdMaximumAsciiStringLength Ascii characters, not including the\r
+  Null-terminator, then ASSERT().\r
+\r
+  If String has no valid decimal digits in the above format, then 0 is stored\r
+  at the location pointed to by Data.\r
+  If the number represented by String exceeds the range defined by UINTN, then\r
+  MAX_UINTN is stored at the location pointed to by Data.\r
+\r
+  If EndPointer is not NULL, a pointer to the character that stopped the scan\r
+  is stored at the location pointed to by EndPointer. If String has no valid\r
+  decimal digits right after the optional pad spaces, the value of String is\r
+  stored at the location pointed to by EndPointer.\r
+\r
+  @param  String                   Pointer to a Null-terminated Ascii string.\r
+  @param  EndPointer               Pointer to character that stops scan.\r
+  @param  Data                     Pointer to the converted value.\r
+\r
+  @retval RETURN_SUCCESS           Value is translated from String.\r
+  @retval RETURN_INVALID_PARAMETER If String is NULL.\r
+                                   If Data is NULL.\r
+                                   If PcdMaximumAsciiStringLength is not zero,\r
+                                   and String contains more than\r
+                                   PcdMaximumAsciiStringLength Ascii\r
+                                   characters, not including the\r
+                                   Null-terminator.\r
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds\r
+                                   the range defined by UINTN.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+AsciiStrDecimalToUintnS (\r
+  IN  CONST CHAR8              *String,\r
+  OUT       CHAR8              **EndPointer,  OPTIONAL\r
+  OUT       UINTN              *Data\r
+  )\r
+{\r
+  //\r
+  // 1. Neither String nor Data shall be a null pointer.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 2. The length of String shall not be greater than ASCII_RSIZE_MAX.\r
+  //\r
+  if (ASCII_RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR8 *) String;\r
+  }\r
+\r
+  //\r
+  // Ignore the pad spaces (space or tab)\r
+  //\r
+  while ((*String == ' ') || (*String == '\t')) {\r
+    String++;\r
+  }\r
+\r
+  //\r
+  // Ignore leading Zeros after the spaces\r
+  //\r
+  while (*String == '0') {\r
+    String++;\r
+  }\r
+\r
+  *Data = 0;\r
+\r
+  while (InternalAsciiIsDecimalDigitCharacter (*String)) {\r
+    //\r
+    // If the number represented by String overflows according to the range\r
+    // defined by UINTN, then MAX_UINTN is stored in *Data and\r
+    // RETURN_UNSUPPORTED is returned.\r
+    //\r
+    if (*Data > ((MAX_UINTN - (*String - '0')) / 10)) {\r
+      *Data = MAX_UINTN;\r
+      if (EndPointer != NULL) {\r
+        *EndPointer = (CHAR8 *) String;\r
+      }\r
+      return RETURN_UNSUPPORTED;\r
+    }\r
+\r
+    *Data = *Data * 10 + (*String - '0');\r
+    String++;\r
+  }\r
+\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR8 *) String;\r
+  }\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Convert a Null-terminated Ascii decimal string to a value of type UINT64.\r
+\r
+  This function outputs a value of type UINT64 by interpreting the contents of\r
+  the Ascii string specified by String as a decimal number. The format of the\r
+  input Ascii string String is:\r
+\r
+                  [spaces] [decimal digits].\r
+\r
+  The valid decimal digit character is in the range [0-9]. The function will\r
+  ignore the pad space, which includes spaces or tab characters, before\r
+  [decimal digits]. The running zero in the beginning of [decimal digits] will\r
+  be ignored. Then, the function stops at the first character that is a not a\r
+  valid decimal character or a Null-terminator, whichever one comes first.\r
+\r
+  If String is NULL, then ASSERT().\r
+  If Data is NULL, then ASSERT().\r
+  If PcdMaximumAsciiStringLength is not zero, and String contains more than\r
+  PcdMaximumAsciiStringLength Ascii characters, not including the\r
+  Null-terminator, then ASSERT().\r
+\r
+  If String has no valid decimal digits in the above format, then 0 is stored\r
+  at the location pointed to by Data.\r
+  If the number represented by String exceeds the range defined by UINT64, then\r
+  MAX_UINT64 is stored at the location pointed to by Data.\r
+\r
+  If EndPointer is not NULL, a pointer to the character that stopped the scan\r
+  is stored at the location pointed to by EndPointer. If String has no valid\r
+  decimal digits right after the optional pad spaces, the value of String is\r
+  stored at the location pointed to by EndPointer.\r
+\r
+  @param  String                   Pointer to a Null-terminated Ascii string.\r
+  @param  EndPointer               Pointer to character that stops scan.\r
+  @param  Data                     Pointer to the converted value.\r
+\r
+  @retval RETURN_SUCCESS           Value is translated from String.\r
+  @retval RETURN_INVALID_PARAMETER If String is NULL.\r
+                                   If Data is NULL.\r
+                                   If PcdMaximumAsciiStringLength is not zero,\r
+                                   and String contains more than\r
+                                   PcdMaximumAsciiStringLength Ascii\r
+                                   characters, not including the\r
+                                   Null-terminator.\r
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds\r
+                                   the range defined by UINT64.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+AsciiStrDecimalToUint64S (\r
+  IN  CONST CHAR8              *String,\r
+  OUT       CHAR8              **EndPointer,  OPTIONAL\r
+  OUT       UINT64             *Data\r
+  )\r
+{\r
+  //\r
+  // 1. Neither String nor Data shall be a null pointer.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 2. The length of String shall not be greater than ASCII_RSIZE_MAX.\r
+  //\r
+  if (ASCII_RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR8 *) String;\r
+  }\r
+\r
+  //\r
+  // Ignore the pad spaces (space or tab)\r
+  //\r
+  while ((*String == ' ') || (*String == '\t')) {\r
+    String++;\r
+  }\r
+\r
+  //\r
+  // Ignore leading Zeros after the spaces\r
+  //\r
+  while (*String == '0') {\r
+    String++;\r
+  }\r
+\r
+  *Data = 0;\r
+\r
+  while (InternalAsciiIsDecimalDigitCharacter (*String)) {\r
+    //\r
+    // If the number represented by String overflows according to the range\r
+    // defined by UINT64, then MAX_UINT64 is stored in *Data and\r
+    // RETURN_UNSUPPORTED is returned.\r
+    //\r
+    if (*Data > DivU64x32 (MAX_UINT64 - (*String - '0'), 10)) {\r
+      *Data = MAX_UINT64;\r
+      if (EndPointer != NULL) {\r
+        *EndPointer = (CHAR8 *) String;\r
+      }\r
+      return RETURN_UNSUPPORTED;\r
+    }\r
+\r
+    *Data = MultU64x32 (*Data, 10) + (*String - '0');\r
+    String++;\r
+  }\r
+\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR8 *) String;\r
+  }\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Convert a Null-terminated Ascii hexadecimal string to a value of type UINTN.\r
+\r
+  This function outputs a value of type UINTN by interpreting the contents of\r
+  the Ascii string specified by String as a hexadecimal number. The format of\r
+  the input Ascii string String is:\r
+\r
+                  [spaces][zeros][x][hexadecimal digits].\r
+\r
+  The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
+  The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If\r
+  "x" appears in the input string, it must be prefixed with at least one 0. The\r
+  function will ignore the pad space, which includes spaces or tab characters,\r
+  before [zeros], [x] or [hexadecimal digits]. The running zero before [x] or\r
+  [hexadecimal digits] will be ignored. Then, the decoding starts after [x] or\r
+  the first valid hexadecimal digit. Then, the function stops at the first\r
+  character that is a not a valid hexadecimal character or Null-terminator,\r
+  whichever on comes first.\r
+\r
+  If String is NULL, then ASSERT().\r
+  If Data is NULL, then ASSERT().\r
+  If PcdMaximumAsciiStringLength is not zero, and String contains more than\r
+  PcdMaximumAsciiStringLength Ascii characters, not including the\r
+  Null-terminator, then ASSERT().\r
+\r
+  If String has no valid hexadecimal digits in the above format, then 0 is\r
+  stored at the location pointed to by Data.\r
+  If the number represented by String exceeds the range defined by UINTN, then\r
+  MAX_UINTN is stored at the location pointed to by Data.\r
+\r
+  If EndPointer is not NULL, a pointer to the character that stopped the scan\r
+  is stored at the location pointed to by EndPointer. If String has no valid\r
+  hexadecimal digits right after the optional pad spaces, the value of String\r
+  is stored at the location pointed to by EndPointer.\r
+\r
+  @param  String                   Pointer to a Null-terminated Ascii string.\r
+  @param  EndPointer               Pointer to character that stops scan.\r
+  @param  Data                     Pointer to the converted value.\r
+\r
+  @retval RETURN_SUCCESS           Value is translated from String.\r
+  @retval RETURN_INVALID_PARAMETER If String is NULL.\r
+                                   If Data is NULL.\r
+                                   If PcdMaximumAsciiStringLength is not zero,\r
+                                   and String contains more than\r
+                                   PcdMaximumAsciiStringLength Ascii\r
+                                   characters, not including the\r
+                                   Null-terminator.\r
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds\r
+                                   the range defined by UINTN.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+AsciiStrHexToUintnS (\r
+  IN  CONST CHAR8              *String,\r
+  OUT       CHAR8              **EndPointer,  OPTIONAL\r
+  OUT       UINTN              *Data\r
+  )\r
+{\r
+  //\r
+  // 1. Neither String nor Data shall be a null pointer.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 2. The length of String shall not be greater than ASCII_RSIZE_MAX.\r
+  //\r
+  if (ASCII_RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR8 *) String;\r
+  }\r
+\r
+  //\r
+  // Ignore the pad spaces (space or tab)\r
+  //\r
+  while ((*String == ' ') || (*String == '\t')) {\r
+    String++;\r
+  }\r
+\r
+  //\r
+  // Ignore leading Zeros after the spaces\r
+  //\r
+  while (*String == '0') {\r
+    String++;\r
+  }\r
+\r
+  if (InternalBaseLibAsciiToUpper (*String) == 'X') {\r
+    if (*(String - 1) != '0') {\r
+      *Data = 0;\r
+      return RETURN_SUCCESS;\r
+    }\r
+    //\r
+    // Skip the 'X'\r
+    //\r
+    String++;\r
+  }\r
+\r
+  *Data = 0;\r
+\r
+  while (InternalAsciiIsHexaDecimalDigitCharacter (*String)) {\r
+    //\r
+    // If the number represented by String overflows according to the range\r
+    // defined by UINTN, then MAX_UINTN is stored in *Data and\r
+    // RETURN_UNSUPPORTED is returned.\r
+    //\r
+    if (*Data > ((MAX_UINTN - InternalAsciiHexCharToUintn (*String)) >> 4)) {\r
+      *Data = MAX_UINTN;\r
+      if (EndPointer != NULL) {\r
+        *EndPointer = (CHAR8 *) String;\r
+      }\r
+      return RETURN_UNSUPPORTED;\r
+    }\r
+\r
+    *Data = (*Data << 4) + InternalAsciiHexCharToUintn (*String);\r
+    String++;\r
+  }\r
+\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR8 *) String;\r
+  }\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Convert a Null-terminated Ascii hexadecimal string to a value of type UINT64.\r
+\r
+  This function outputs a value of type UINT64 by interpreting the contents of\r
+  the Ascii string specified by String as a hexadecimal number. The format of\r
+  the input Ascii string String is:\r
+\r
+                  [spaces][zeros][x][hexadecimal digits].\r
+\r
+  The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
+  The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If\r
+  "x" appears in the input string, it must be prefixed with at least one 0. The\r
+  function will ignore the pad space, which includes spaces or tab characters,\r
+  before [zeros], [x] or [hexadecimal digits]. The running zero before [x] or\r
+  [hexadecimal digits] will be ignored. Then, the decoding starts after [x] or\r
+  the first valid hexadecimal digit. Then, the function stops at the first\r
+  character that is a not a valid hexadecimal character or Null-terminator,\r
+  whichever on comes first.\r
+\r
+  If String is NULL, then ASSERT().\r
+  If Data is NULL, then ASSERT().\r
+  If PcdMaximumAsciiStringLength is not zero, and String contains more than\r
+  PcdMaximumAsciiStringLength Ascii characters, not including the\r
+  Null-terminator, then ASSERT().\r
+\r
+  If String has no valid hexadecimal digits in the above format, then 0 is\r
+  stored at the location pointed to by Data.\r
+  If the number represented by String exceeds the range defined by UINT64, then\r
+  MAX_UINT64 is stored at the location pointed to by Data.\r
+\r
+  If EndPointer is not NULL, a pointer to the character that stopped the scan\r
+  is stored at the location pointed to by EndPointer. If String has no valid\r
+  hexadecimal digits right after the optional pad spaces, the value of String\r
+  is stored at the location pointed to by EndPointer.\r
+\r
+  @param  String                   Pointer to a Null-terminated Ascii string.\r
+  @param  EndPointer               Pointer to character that stops scan.\r
+  @param  Data                     Pointer to the converted value.\r
+\r
+  @retval RETURN_SUCCESS           Value is translated from String.\r
+  @retval RETURN_INVALID_PARAMETER If String is NULL.\r
+                                   If Data is NULL.\r
+                                   If PcdMaximumAsciiStringLength is not zero,\r
+                                   and String contains more than\r
+                                   PcdMaximumAsciiStringLength Ascii\r
+                                   characters, not including the\r
+                                   Null-terminator.\r
+  @retval RETURN_UNSUPPORTED       If the number represented by String exceeds\r
+                                   the range defined by UINT64.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+AsciiStrHexToUint64S (\r
+  IN  CONST CHAR8              *String,\r
+  OUT       CHAR8              **EndPointer,  OPTIONAL\r
+  OUT       UINT64             *Data\r
+  )\r
+{\r
+  //\r
+  // 1. Neither String nor Data shall be a null pointer.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 2. The length of String shall not be greater than ASCII_RSIZE_MAX.\r
+  //\r
+  if (ASCII_RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR8 *) String;\r
+  }\r
+\r
+  //\r
+  // Ignore the pad spaces (space or tab)\r
+  //\r
+  while ((*String == ' ') || (*String == '\t')) {\r
+    String++;\r
+  }\r
+\r
+  //\r
+  // Ignore leading Zeros after the spaces\r
+  //\r
+  while (*String == '0') {\r
+    String++;\r
+  }\r
+\r
+  if (InternalBaseLibAsciiToUpper (*String) == 'X') {\r
+    if (*(String - 1) != '0') {\r
+      *Data = 0;\r
+      return RETURN_SUCCESS;\r
+    }\r
+    //\r
+    // Skip the 'X'\r
+    //\r
+    String++;\r
+  }\r
+\r
+  *Data = 0;\r
+\r
+  while (InternalAsciiIsHexaDecimalDigitCharacter (*String)) {\r
+    //\r
+    // If the number represented by String overflows according to the range\r
+    // defined by UINT64, then MAX_UINT64 is stored in *Data and\r
+    // RETURN_UNSUPPORTED is returned.\r
+    //\r
+    if (*Data > RShiftU64 (MAX_UINT64 - InternalAsciiHexCharToUintn (*String), 4)) {\r
+      *Data = MAX_UINT64;\r
+      if (EndPointer != NULL) {\r
+        *EndPointer = (CHAR8 *) String;\r
+      }\r
+      return RETURN_UNSUPPORTED;\r
+    }\r
+\r
+    *Data = LShiftU64 (*Data, 4) + InternalAsciiHexCharToUintn (*String);\r
+    String++;\r
+  }\r
 \r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR8 *) String;\r
+  }\r
   return RETURN_SUCCESS;\r
 }\r
 \r
 /**\r
-  Appends not more than Length successive char from the string pointed to by\r
-  Source to the end of the string pointed to by Destination. If no null char is\r
-  copied from Source, then Destination[StrLen(Destination) + Length] is always\r
-  set to null.\r
+  Convert a Null-terminated Unicode string to a Null-terminated\r
+  ASCII string.\r
 \r
-  This function is similar as strncat_s defined in C11.\r
+  This function is similar to AsciiStrCpyS.\r
+\r
+  This function converts the content of the Unicode string Source\r
+  to the ASCII string Destination by copying the lower 8 bits of\r
+  each Unicode character. The function terminates the ASCII string\r
+  Destination by appending a Null-terminator character at the end.\r
+\r
+  The caller is responsible to make sure Destination points to a buffer with size\r
+  equal or greater than ((StrLen (Source) + 1) * sizeof (CHAR8)) in bytes.\r
 \r
+  If any Unicode characters in Source contain non-zero value in\r
+  the upper 8 bits, then ASSERT().\r
+\r
+  If Source is not aligned on a 16-bit boundary, then ASSERT().\r
   If an error would be returned, then the function will also ASSERT().\r
 \r
   If an error is returned, then the Destination is unmodified.\r
 \r
-  @param  Destination              A pointer to a Null-terminated Ascii string.\r
-  @param  DestMax                  The maximum number of Destination Ascii\r
-                                   char, including terminating null char.\r
-  @param  Source                   A pointer to a Null-terminated Ascii string.\r
-  @param  Length                   The maximum number of Ascii characters to copy.\r
+  @param  Source        The pointer to a Null-terminated Unicode string.\r
+  @param  Destination   The pointer to a Null-terminated ASCII string.\r
+  @param  DestMax       The maximum number of Destination Ascii\r
+                        char, including terminating null char.\r
 \r
-  @retval RETURN_SUCCESS           String is appended.\r
-  @retval RETURN_BAD_BUFFER_SIZE   If DestMax is NOT greater than\r
-                                   StrLen(Destination).\r
-  @retval RETURN_BUFFER_TOO_SMALL  If (DestMax - StrLen(Destination)) is NOT\r
-                                   greater than MIN(StrLen(Source), Length).\r
+  @retval RETURN_SUCCESS           String is converted.\r
+  @retval RETURN_BUFFER_TOO_SMALL  If DestMax is NOT greater than StrLen(Source).\r
   @retval RETURN_INVALID_PARAMETER If Destination is NULL.\r
                                    If Source is NULL.\r
                                    If PcdMaximumAsciiStringLength is not zero,\r
-                                    and DestMax is greater than \r
+                                    and DestMax is greater than\r
                                     PcdMaximumAsciiStringLength.\r
+                                   If PcdMaximumUnicodeStringLength is not zero,\r
+                                    and DestMax is greater than\r
+                                    PcdMaximumUnicodeStringLength.\r
                                    If DestMax is 0.\r
   @retval RETURN_ACCESS_DENIED     If Source and Destination overlap.\r
+\r
 **/\r
 RETURN_STATUS\r
 EFIAPI\r
-AsciiStrnCatS (\r
-  IN OUT CHAR8        *Destination,\r
-  IN     UINTN        DestMax,\r
-  IN     CONST CHAR8  *Source,\r
-  IN     UINTN        Length\r
+UnicodeStrToAsciiStrS (\r
+  IN      CONST CHAR16              *Source,\r
+  OUT     CHAR8                     *Destination,\r
+  IN      UINTN                     DestMax\r
   )\r
 {\r
-  UINTN               DestLen;\r
-  UINTN               CopyLen;\r
-  UINTN               SourceLen;\r
-  \r
+  UINTN            SourceLen;\r
+\r
+  ASSERT (((UINTN) Source & BIT0) == 0);\r
+\r
   //\r
-  // Let CopyLen denote the value DestMax - AsciiStrnLenS(Destination, DestMax) upon entry to AsciiStrnCatS.\r
+  // 1. Neither Destination nor Source shall be a null pointer.\r
   //\r
-  DestLen = AsciiStrnLenS (Destination, DestMax);\r
-  CopyLen = DestMax - DestLen;\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 2. DestMax shall not be greater than ASCII_RSIZE_MAX or RSIZE_MAX.\r
+  //\r
+  if (ASCII_RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+  if (RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  //\r
+  // 3. DestMax shall not equal zero.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 4. DestMax shall be greater than StrnLenS (Source, DestMax).\r
+  //\r
+  SourceLen = StrnLenS (Source, DestMax);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);\r
+\r
+  //\r
+  // 5. Copying shall not take place between objects that overlap.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), RETURN_ACCESS_DENIED);\r
+\r
+  //\r
+  // convert string\r
+  //\r
+  while (*Source != '\0') {\r
+    //\r
+    // If any Unicode characters in Source contain\r
+    // non-zero value in the upper 8 bits, then ASSERT().\r
+    //\r
+    ASSERT (*Source < 0x100);\r
+    *(Destination++) = (CHAR8) *(Source++);\r
+  }\r
+  *Destination = '\0';\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Convert not more than Length successive characters from a Null-terminated\r
+  Unicode string to a Null-terminated Ascii string. If no null char is copied\r
+  from Source, then Destination[Length] is always set to null.\r
+\r
+  This function converts not more than Length successive characters from the\r
+  Unicode string Source to the Ascii string Destination by copying the lower 8\r
+  bits of each Unicode character. The function terminates the Ascii string\r
+  Destination by appending a Null-terminator character at the end.\r
+\r
+  The caller is responsible to make sure Destination points to a buffer with\r
+  size not smaller than ((MIN(StrLen(Source), Length) + 1) * sizeof (CHAR8))\r
+  in bytes.\r
+\r
+  If any Unicode characters in Source contain non-zero value in the upper 8\r
+  bits, then ASSERT().\r
+  If Source is not aligned on a 16-bit boundary, then ASSERT().\r
+  If an error would be returned, then the function will also ASSERT().\r
+\r
+  If an error is returned, then Destination and DestinationLength are\r
+  unmodified.\r
+\r
+  @param  Source             The pointer to a Null-terminated Unicode string.\r
+  @param  Length             The maximum number of Unicode characters to\r
+                             convert.\r
+  @param  Destination        The pointer to a Null-terminated Ascii string.\r
+  @param  DestMax            The maximum number of Destination Ascii char,\r
+                             including terminating null char.\r
+  @param  DestinationLength  The number of Unicode characters converted.\r
+\r
+  @retval RETURN_SUCCESS            String is converted.\r
+  @retval RETURN_INVALID_PARAMETER  If Destination is NULL.\r
+                                    If Source is NULL.\r
+                                    If DestinationLength is NULL.\r
+                                    If PcdMaximumAsciiStringLength is not zero,\r
+                                    and Length or DestMax is greater than\r
+                                    PcdMaximumAsciiStringLength.\r
+                                    If PcdMaximumUnicodeStringLength is not\r
+                                    zero, and Length or DestMax is greater than\r
+                                    PcdMaximumUnicodeStringLength.\r
+                                    If DestMax is 0.\r
+  @retval RETURN_BUFFER_TOO_SMALL   If DestMax is NOT greater than\r
+                                    MIN(StrLen(Source), Length).\r
+  @retval RETURN_ACCESS_DENIED      If Source and Destination overlap.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+UnicodeStrnToAsciiStrS (\r
+  IN      CONST CHAR16              *Source,\r
+  IN      UINTN                     Length,\r
+  OUT     CHAR8                     *Destination,\r
+  IN      UINTN                     DestMax,\r
+  OUT     UINTN                     *DestinationLength\r
+  )\r
+{\r
+  UINTN            SourceLen;\r
+\r
+  ASSERT (((UINTN) Source & BIT0) == 0);\r
+\r
+  //\r
+  // 1. None of Destination, Source or DestinationLength shall be a null\r
+  // pointer.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((DestinationLength != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 2. Neither Length nor DestMax shall be greater than ASCII_RSIZE_MAX or\r
+  // RSIZE_MAX.\r
+  //\r
+  if (ASCII_RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+  if (RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  //\r
+  // 3. DestMax shall not equal zero.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 4. If Length is not less than DestMax, then DestMax shall be greater than\r
+  // StrnLenS(Source, DestMax).\r
+  //\r
+  SourceLen = StrnLenS (Source, DestMax);\r
+  if (Length >= DestMax) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);\r
+  }\r
+\r
+  //\r
+  // 5. Copying shall not take place between objects that overlap.\r
+  //\r
+  if (SourceLen > Length) {\r
+    SourceLen = Length;\r
+  }\r
+  SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), RETURN_ACCESS_DENIED);\r
+\r
+  *DestinationLength = 0;\r
+\r
+  //\r
+  // Convert string\r
+  //\r
+  while ((*Source != 0) && (SourceLen > 0)) {\r
+    //\r
+    // If any Unicode characters in Source contain non-zero value in the upper\r
+    // 8 bits, then ASSERT().\r
+    //\r
+    ASSERT (*Source < 0x100);\r
+    *(Destination++) = (CHAR8) *(Source++);\r
+    SourceLen--;\r
+    (*DestinationLength)++;\r
+  }\r
+  *Destination = 0;\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Convert one Null-terminated ASCII string to a Null-terminated\r
+  Unicode string.\r
+\r
+  This function is similar to StrCpyS.\r
+\r
+  This function converts the contents of the ASCII string Source to the Unicode\r
+  string Destination. The function terminates the Unicode string Destination by\r
+  appending a Null-terminator character at the end.\r
+\r
+  The caller is responsible to make sure Destination points to a buffer with size\r
+  equal or greater than ((AsciiStrLen (Source) + 1) * sizeof (CHAR16)) in bytes.\r
+\r
+  If Destination is not aligned on a 16-bit boundary, then ASSERT().\r
+  If an error would be returned, then the function will also ASSERT().\r
+\r
+  If an error is returned, then the Destination is unmodified.\r
+\r
+  @param  Source        The pointer to a Null-terminated ASCII string.\r
+  @param  Destination   The pointer to a Null-terminated Unicode string.\r
+  @param  DestMax       The maximum number of Destination Unicode\r
+                        char, including terminating null char.\r
+\r
+  @retval RETURN_SUCCESS           String is converted.\r
+  @retval RETURN_BUFFER_TOO_SMALL  If DestMax is NOT greater than StrLen(Source).\r
+  @retval RETURN_INVALID_PARAMETER If Destination is NULL.\r
+                                   If Source is NULL.\r
+                                   If PcdMaximumUnicodeStringLength is not zero,\r
+                                    and DestMax is greater than\r
+                                    PcdMaximumUnicodeStringLength.\r
+                                   If PcdMaximumAsciiStringLength is not zero,\r
+                                    and DestMax is greater than\r
+                                    PcdMaximumAsciiStringLength.\r
+                                   If DestMax is 0.\r
+  @retval RETURN_ACCESS_DENIED     If Source and Destination overlap.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+AsciiStrToUnicodeStrS (\r
+  IN      CONST CHAR8               *Source,\r
+  OUT     CHAR16                    *Destination,\r
+  IN      UINTN                     DestMax\r
+  )\r
+{\r
+  UINTN            SourceLen;\r
+\r
+  ASSERT (((UINTN) Destination & BIT0) == 0);\r
 \r
   //\r
   // 1. Neither Destination nor Source shall be a null pointer.\r
@@ -893,11 +2900,13 @@ AsciiStrnCatS (
   SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);\r
 \r
   //\r
-  // 2. Neither DestMax nor Length shall be greater than ASCII_RSIZE_MAX.\r
+  // 2. DestMax shall not be greater than RSIZE_MAX or ASCII_RSIZE_MAX.\r
   //\r
+  if (RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
   if (ASCII_RSIZE_MAX != 0) {\r
     SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
-    SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
   }\r
 \r
   //\r
@@ -906,37 +2915,136 @@ AsciiStrnCatS (
   SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);\r
 \r
   //\r
-  // 4. CopyLen shall not equal zero.\r
+  // 4. DestMax shall be greater than AsciiStrnLenS(Source, DestMax).\r
   //\r
-  SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE);\r
+  SourceLen = AsciiStrnLenS (Source, DestMax);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);\r
 \r
   //\r
-  // 5. If Length is not less than CopyLen, then CopyLen shall be greater than AsciiStrnLenS(Source, CopyLen).\r
+  // 5. Copying shall not take place between objects that overlap.\r
   //\r
-  SourceLen = AsciiStrnLenS (Source, CopyLen);\r
-  if (Length >= CopyLen) {\r
-    SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL);\r
+  SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax * sizeof(CHAR16), (VOID *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);\r
+\r
+  //\r
+  // Convert string\r
+  //\r
+  while (*Source != '\0') {\r
+    *(Destination++) = (CHAR16)*(Source++);\r
   }\r
+  *Destination = '\0';\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Convert not more than Length successive characters from a Null-terminated\r
+  Ascii string to a Null-terminated Unicode string. If no null char is copied\r
+  from Source, then Destination[Length] is always set to null.\r
+\r
+  This function converts not more than Length successive characters from the\r
+  Ascii string Source to the Unicode string Destination. The function\r
+  terminates the Unicode string Destination by appending a Null-terminator\r
+  character at the end.\r
+\r
+  The caller is responsible to make sure Destination points to a buffer with\r
+  size not smaller than\r
+  ((MIN(AsciiStrLen(Source), Length) + 1) * sizeof (CHAR8)) in bytes.\r
+\r
+  If Destination is not aligned on a 16-bit boundary, then ASSERT().\r
+  If an error would be returned, then the function will also ASSERT().\r
+\r
+  If an error is returned, then Destination and DestinationLength are\r
+  unmodified.\r
+\r
+  @param  Source             The pointer to a Null-terminated Ascii string.\r
+  @param  Length             The maximum number of Ascii characters to convert.\r
+  @param  Destination        The pointer to a Null-terminated Unicode string.\r
+  @param  DestMax            The maximum number of Destination Unicode char,\r
+                             including terminating null char.\r
+  @param  DestinationLength  The number of Ascii characters converted.\r
+\r
+  @retval RETURN_SUCCESS            String is converted.\r
+  @retval RETURN_INVALID_PARAMETER  If Destination is NULL.\r
+                                    If Source is NULL.\r
+                                    If DestinationLength is NULL.\r
+                                    If PcdMaximumUnicodeStringLength is not\r
+                                    zero, and Length or DestMax is greater than\r
+                                    PcdMaximumUnicodeStringLength.\r
+                                    If PcdMaximumAsciiStringLength is not zero,\r
+                                    and Length or DestMax is greater than\r
+                                    PcdMaximumAsciiStringLength.\r
+                                    If DestMax is 0.\r
+  @retval RETURN_BUFFER_TOO_SMALL   If DestMax is NOT greater than\r
+                                    MIN(AsciiStrLen(Source), Length).\r
+  @retval RETURN_ACCESS_DENIED      If Source and Destination overlap.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+AsciiStrnToUnicodeStrS (\r
+  IN      CONST CHAR8               *Source,\r
+  IN      UINTN                     Length,\r
+  OUT     CHAR16                    *Destination,\r
+  IN      UINTN                     DestMax,\r
+  OUT     UINTN                     *DestinationLength\r
+  )\r
+{\r
+  UINTN            SourceLen;\r
+\r
+  ASSERT (((UINTN) Destination & BIT0) == 0);\r
 \r
   //\r
-  // 6. Copying shall not take place between objects that overlap.\r
+  // 1. None of Destination, Source or DestinationLength shall be a null\r
+  // pointer.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((DestinationLength != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 2. Neither Length nor DestMax shall be greater than ASCII_RSIZE_MAX or\r
+  // RSIZE_MAX.\r
+  //\r
+  if (RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+  if (ASCII_RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  //\r
+  // 3. DestMax shall not equal zero.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 4. If Length is not less than DestMax, then DestMax shall be greater than\r
+  // AsciiStrnLenS(Source, DestMax).\r
+  //\r
+  SourceLen = AsciiStrnLenS (Source, DestMax);\r
+  if (Length >= DestMax) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);\r
+  }\r
+\r
+  //\r
+  // 5. Copying shall not take place between objects that overlap.\r
   //\r
   if (SourceLen > Length) {\r
     SourceLen = Length;\r
   }\r
-  SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);\r
+  SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax * sizeof(CHAR16), (VOID *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);\r
+\r
+  *DestinationLength = 0;\r
 \r
   //\r
-  // The AsciiStrnCatS function appends not more than Length successive characters (characters\r
-  // that follow a null character are not copied) from the array pointed to by Source to the end of\r
-  // the string pointed to by Destination. The initial character from Source overwrites the null character at\r
-  // the end of Destination. If no null character was copied from Source, then Destination[DestMax-CopyLen+Length] is set to\r
-  // a null character.\r
+  // Convert string\r
   //\r
-  Destination = Destination + DestLen;\r
   while ((*Source != 0) && (SourceLen > 0)) {\r
-    *(Destination++) = *(Source++);\r
+    *(Destination++) = (CHAR16)*(Source++);\r
     SourceLen--;\r
+    (*DestinationLength)++;\r
   }\r
   *Destination = 0;\r
 \r