]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/Common/CommonLib.c
BaseTools: Fix compile error on VS2010
[mirror_edk2.git] / BaseTools / Source / C / Common / CommonLib.c
index 4a62bec85e03d3816a823de8331b035c5fa3b460..90cc578e619d3250a317261d3021276ad154b466 100644 (file)
@@ -24,6 +24,14 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "CommonLib.h"\r
 #include "EfiUtilityMsgs.h"\r
 \r
+#define SAFE_STRING_CONSTRAINT_CHECK(Expression, Status)  \\r
+  do { \\r
+    ASSERT (Expression); \\r
+    if (!(Expression)) { \\r
+      return Status; \\r
+    } \\r
+  } while (FALSE)\r
+\r
 VOID\r
 PeiZeroMem (\r
   IN VOID   *Buffer,\r
@@ -731,3 +739,1624 @@ Returns:
   return PathPointer;\r
 #endif\r
 }\r
+\r
+CHAR16\r
+InternalCharToUpper (\r
+        CHAR16                    Char\r
+  )\r
+{\r
+  if (Char >= L'a' && Char <= L'z') {\r
+    return (CHAR16) (Char - (L'a' - L'A'));\r
+  }\r
+\r
+  return Char;\r
+}\r
+\r
+UINTN\r
+StrnLenS (\r
+   CONST CHAR16              *String,\r
+   UINTN                     MaxSize\r
+  )\r
+{\r
+  UINTN     Length;\r
+\r
+  ASSERT (((UINTN) String & BIT0) == 0);\r
+\r
+  //\r
+  // If String is a null pointer or MaxSize is 0, then the StrnLenS function returns zero.\r
+  //\r
+  if ((String == NULL) || (MaxSize == 0)) {\r
+    return 0;\r
+  }\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
+VOID *\r
+InternalAllocatePool (\r
+   UINTN   AllocationSize\r
+  )\r
+{\r
+  VOID * Memory;\r
+\r
+  Memory = malloc(AllocationSize);\r
+  ASSERT(Memory != NULL);\r
+  return Memory;\r
+}\r
+\r
+\r
+VOID *\r
+InternalReallocatePool (\r
+   UINTN            OldSize,\r
+   UINTN            NewSize,\r
+   VOID             *OldBuffer  OPTIONAL\r
+  )\r
+{\r
+  VOID  *NewBuffer;\r
+\r
+  NewBuffer = AllocateZeroPool (NewSize);\r
+  if (NewBuffer != NULL && OldBuffer != NULL) {\r
+    memcpy (NewBuffer, OldBuffer, MIN (OldSize, NewSize));\r
+    free(OldBuffer);\r
+  }\r
+  return NewBuffer;\r
+}\r
+\r
+VOID *\r
+ReallocatePool (\r
+   UINTN  OldSize,\r
+   UINTN  NewSize,\r
+   VOID   *OldBuffer  OPTIONAL\r
+  )\r
+{\r
+  return InternalReallocatePool (OldSize, NewSize, OldBuffer);\r
+}\r
+\r
+/**\r
+  Returns the length of a Null-terminated Unicode string.\r
+\r
+  This function returns the number of Unicode characters in the Null-terminated\r
+  Unicode string specified by String.\r
+\r
+  If String is NULL, then ASSERT().\r
+  If String is not aligned on a 16-bit boundary, then ASSERT().\r
+  If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
+  PcdMaximumUnicodeStringLength Unicode characters, not including the\r
+  Null-terminator, then ASSERT().\r
+\r
+  @param  String  A pointer to a Null-terminated Unicode string.\r
+\r
+  @return The length of String.\r
+\r
+**/\r
+UINTN\r
+StrLen (\r
+  CONST CHAR16              *String\r
+  )\r
+{\r
+  UINTN   Length;\r
+\r
+  ASSERT (String != NULL);\r
+  ASSERT (((UINTN) String & BIT0) == 0);\r
+\r
+  for (Length = 0; *String != L'\0'; String++, Length++) {\r
+    //\r
+    // If PcdMaximumUnicodeStringLength is not zero,\r
+    // length should not more than PcdMaximumUnicodeStringLength\r
+    //\r
+  }\r
+  return Length;\r
+}\r
+\r
+BOOLEAN\r
+InternalSafeStringIsOverlap (\r
+  IN VOID    *Base1,\r
+  IN UINTN   Size1,\r
+  IN VOID    *Base2,\r
+  IN UINTN   Size2\r
+  )\r
+{\r
+  if ((((UINTN)Base1 >= (UINTN)Base2) && ((UINTN)Base1 < (UINTN)Base2 + Size2)) ||\r
+      (((UINTN)Base2 >= (UINTN)Base1) && ((UINTN)Base2 < (UINTN)Base1 + Size1))) {\r
+    return TRUE;\r
+  }\r
+  return FALSE;\r
+}\r
+\r
+BOOLEAN\r
+InternalSafeStringNoStrOverlap (\r
+  IN CHAR16  *Str1,\r
+  IN UINTN   Size1,\r
+  IN CHAR16  *Str2,\r
+  IN UINTN   Size2\r
+  )\r
+{\r
+  return !InternalSafeStringIsOverlap (Str1, Size1 * sizeof(CHAR16), Str2, Size2 * sizeof(CHAR16));\r
+}\r
+\r
+RETURN_STATUS\r
+StrDecimalToUintnS (\r
+    CONST CHAR16             *String,\r
+         CHAR16             **EndPointer,  OPTIONAL\r
+         UINTN              *Data\r
+  )\r
+{\r
+  ASSERT (((UINTN) String & BIT0) == 0);\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 RSIZE_MAX.\r
+  //\r
+  if (RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR16 *) String;\r
+  }\r
+\r
+  //\r
+  // Ignore the pad spaces (space or tab)\r
+  //\r
+  while ((*String == L' ') || (*String == L'\t')) {\r
+    String++;\r
+  }\r
+\r
+  //\r
+  // Ignore leading Zeros after the spaces\r
+  //\r
+  while (*String == L'0') {\r
+    String++;\r
+  }\r
+\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
+  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
+**/\r
+RETURN_STATUS\r
+StrDecimalToUint64S (\r
+    CONST CHAR16             *String,\r
+         CHAR16             **EndPointer,  OPTIONAL\r
+         UINT64             *Data\r
+  )\r
+{\r
+  ASSERT (((UINTN) String & BIT0) == 0);\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 RSIZE_MAX.\r
+  //\r
+  if (RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR16 *) String;\r
+  }\r
+\r
+  //\r
+  // Ignore the pad spaces (space or tab)\r
+  //\r
+  while ((*String == L' ') || (*String == L'\t')) {\r
+    String++;\r
+  }\r
+\r
+  //\r
+  // Ignore leading Zeros after the spaces\r
+  //\r
+  while (*String == L'0') {\r
+    String++;\r
+  }\r
+\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 > ((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 = (*Data) * 10 + (*String - L'0');\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 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
+**/\r
+RETURN_STATUS\r
+StrHexToUintnS (\r
+    CONST CHAR16             *String,\r
+         CHAR16             **EndPointer,  OPTIONAL\r
+         UINTN              *Data\r
+  )\r
+{\r
+  ASSERT (((UINTN) String & BIT0) == 0);\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 RSIZE_MAX.\r
+  //\r
+  if (RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR16 *) String;\r
+  }\r
+\r
+  //\r
+  // Ignore the pad spaces (space or tab)\r
+  //\r
+  while ((*String == L' ') || (*String == L'\t')) {\r
+    String++;\r
+  }\r
+\r
+  //\r
+  // Ignore leading Zeros after the spaces\r
+  //\r
+  while (*String == L'0') {\r
+    String++;\r
+  }\r
+\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
+\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR16 *) String;\r
+  }\r
+  return RETURN_SUCCESS;\r
+}\r
+RETURN_STATUS\r
+StrHexToUint64S (\r
+    CONST CHAR16             *String,\r
+         CHAR16             **EndPointer,  OPTIONAL\r
+         UINT64             *Data\r
+  )\r
+{\r
+  ASSERT (((UINTN) String & BIT0) == 0);\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 RSIZE_MAX.\r
+  //\r
+  if (RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR16 *) String;\r
+  }\r
+\r
+  //\r
+  // Ignore the pad spaces (space or tab)\r
+  //\r
+  while ((*String == L' ') || (*String == L'\t')) {\r
+    String++;\r
+  }\r
+\r
+  //\r
+  // Ignore leading Zeros after the spaces\r
+  //\r
+  while (*String == L'0') {\r
+    String++;\r
+  }\r
+\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 UINT64, then MAX_UINT64 is stored in *Data and\r
+    // RETURN_UNSUPPORTED is returned.\r
+    //\r
+    if (*Data > ((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 =  ((*Data) << 4) + InternalHexCharToUintn (*String);\r
+    String++;\r
+  }\r
+\r
+  if (EndPointer != NULL) {\r
+    *EndPointer = (CHAR16 *) String;\r
+  }\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+UINT64\r
+StrDecimalToUint64 (\r
+  CONST CHAR16              *String\r
+  )\r
+{\r
+  UINT64     Result;\r
+\r
+  StrDecimalToUint64S (String, (CHAR16 **) NULL, &Result);\r
+  return Result;\r
+}\r
+\r
+\r
+UINT64\r
+StrHexToUint64 (\r
+  CONST CHAR16             *String\r
+  )\r
+{\r
+  UINT64    Result;\r
+\r
+  StrHexToUint64S (String, (CHAR16 **) NULL, &Result);\r
+  return Result;\r
+}\r
+\r
+UINTN\r
+StrDecimalToUintn (\r
+  CONST CHAR16              *String\r
+  )\r
+{\r
+  UINTN     Result;\r
+\r
+  StrDecimalToUintnS (String, (CHAR16 **) NULL, &Result);\r
+  return Result;\r
+}\r
+\r
+UINTN\r
+StrHexToUintn (\r
+  CONST CHAR16              *String\r
+  )\r
+{\r
+  UINTN     Result;\r
+\r
+  StrHexToUintnS (String, (CHAR16 **) NULL, &Result);\r
+  return Result;\r
+}\r
+\r
+UINTN\r
+StrSize (\r
+  CONST CHAR16              *String\r
+  )\r
+{\r
+  return (StrLen (String) + 1) * sizeof (*String);\r
+}\r
+\r
+\r
+UINT64\r
+ReadUnaligned64 (\r
+   CONST UINT64              *Buffer\r
+  )\r
+{\r
+  ASSERT (Buffer != NULL);\r
+\r
+  return *Buffer;\r
+}\r
+\r
+UINT64\r
+WriteUnaligned64 (\r
+   UINT64                    *Buffer,\r
+   UINT64                    Value\r
+  )\r
+{\r
+  ASSERT (Buffer != NULL);\r
+\r
+  return *Buffer = Value;\r
+}\r
+\r
+\r
+EFI_GUID *\r
+CopyGuid (\r
+   EFI_GUID         *DestinationGuid,\r
+   CONST EFI_GUID  *SourceGuid\r
+  )\r
+{\r
+  WriteUnaligned64 (\r
+    (UINT64*)DestinationGuid,\r
+    ReadUnaligned64 ((CONST UINT64*)SourceGuid)\r
+    );\r
+  WriteUnaligned64 (\r
+    (UINT64*)DestinationGuid + 1,\r
+    ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1)\r
+    );\r
+  return DestinationGuid;\r
+}\r
+\r
+UINT16\r
+SwapBytes16 (\r
+  UINT16                    Value\r
+  )\r
+{\r
+  return (UINT16) ((Value<< 8) | (Value>> 8));\r
+}\r
+\r
+\r
+UINT32\r
+SwapBytes32 (\r
+  UINT32                    Value\r
+  )\r
+{\r
+  UINT32  LowerBytes;\r
+  UINT32  HigherBytes;\r
+\r
+  LowerBytes  = (UINT32) SwapBytes16 ((UINT16) Value);\r
+  HigherBytes = (UINT32) SwapBytes16 ((UINT16) (Value >> 16));\r
+  return (LowerBytes << 16 | HigherBytes);\r
+}\r
+\r
+BOOLEAN\r
+InternalIsDecimalDigitCharacter (\r
+  CHAR16                    Char\r
+  )\r
+{\r
+  return (BOOLEAN) (Char >= L'0' && Char <= L'9');\r
+}\r
+\r
+VOID *\r
+InternalAllocateCopyPool (\r
+   UINTN            AllocationSize,\r
+   CONST VOID       *Buffer\r
+  )\r
+{\r
+  VOID  *Memory;\r
+\r
+  ASSERT (Buffer != NULL);\r
+  ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));\r
+\r
+  Memory = malloc (AllocationSize);\r
+  if (Memory != NULL) {\r
+     Memory = memcpy (Memory, Buffer, AllocationSize);\r
+  }\r
+  return Memory;\r
+}\r
+\r
+BOOLEAN\r
+InternalIsHexaDecimalDigitCharacter (\r
+  CHAR16                    Char\r
+  )\r
+{\r
+\r
+  return (BOOLEAN) (InternalIsDecimalDigitCharacter (Char) ||\r
+    (Char >= L'A' && Char <= L'F') ||\r
+    (Char >= L'a' && Char <= L'f'));\r
+}\r
+\r
+UINTN\r
+InternalHexCharToUintn (\r
+        CHAR16                    Char\r
+  )\r
+{\r
+  if (InternalIsDecimalDigitCharacter (Char)) {\r
+    return Char - L'0';\r
+  }\r
+\r
+  return (10 + InternalCharToUpper (Char) - L'A');\r
+}\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
+StrHexToBytes (\r
+   CONST CHAR16       *String,\r
+   UINTN              Length,\r
+   UINT8              *Buffer,\r
+   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
+  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
+StrToGuid (\r
+   CONST CHAR16       *String,\r
+   EFI_GUID           *Guid\r
+  )\r
+{\r
+  RETURN_STATUS          Status;\r
+  EFI_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
+  Compares up to a specified length the contents of two Null-terminated Unicode strings,\r
+  and returns the difference between the first mismatched Unicode characters.\r
+\r
+  This function compares the Null-terminated Unicode string FirstString to the\r
+  Null-terminated Unicode string SecondString. At most, Length Unicode\r
+  characters will be compared. If Length is 0, then 0 is returned. If\r
+  FirstString is identical to SecondString, then 0 is returned. Otherwise, the\r
+  value returned is the first mismatched Unicode character in SecondString\r
+  subtracted from the first mismatched Unicode character in FirstString.\r
+\r
+  If Length > 0 and FirstString is NULL, then ASSERT().\r
+  If Length > 0 and FirstString is not aligned on a 16-bit boundary, then ASSERT().\r
+  If Length > 0 and SecondString is NULL, then ASSERT().\r
+  If Length > 0 and SecondString is not aligned on a 16-bit boundary, then ASSERT().\r
+  If PcdMaximumUnicodeStringLength is not zero, and Length is greater than\r
+  PcdMaximumUnicodeStringLength, then ASSERT().\r
+  If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more than\r
+  PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,\r
+  then ASSERT().\r
+  If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more than\r
+  PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,\r
+  then ASSERT().\r
+\r
+  @param  FirstString   A pointer to a Null-terminated Unicode string.\r
+  @param  SecondString  A pointer to a Null-terminated Unicode string.\r
+  @param  Length        The maximum number of Unicode characters to compare.\r
+\r
+  @retval 0      FirstString is identical to SecondString.\r
+  @return others FirstString is not identical to SecondString.\r
+\r
+**/\r
+INTN\r
+StrnCmp (\r
+        CONST CHAR16              *FirstString,\r
+        CONST CHAR16              *SecondString,\r
+        UINTN                     Length\r
+  )\r
+{\r
+  if (Length == 0) {\r
+    return 0;\r
+  }\r
+\r
+  //\r
+  // ASSERT both strings are less long than PcdMaximumUnicodeStringLength.\r
+  // Length tests are performed inside StrLen().\r
+  //\r
+  ASSERT (StrSize (FirstString) != 0);\r
+  ASSERT (StrSize (SecondString) != 0);\r
+\r
+  while ((*FirstString != L'\0') &&\r
+         (*SecondString != L'\0') &&\r
+         (*FirstString == *SecondString) &&\r
+         (Length > 1)) {\r
+    FirstString++;\r
+    SecondString++;\r
+    Length--;\r
+  }\r
+\r
+  return *FirstString - *SecondString;\r
+}\r
+\r
+VOID *\r
+AllocateCopyPool (\r
+   UINTN       AllocationSize,\r
+   CONST VOID  *Buffer\r
+  )\r
+{\r
+  return InternalAllocateCopyPool (AllocationSize, Buffer);\r
+}\r
+\r
+INTN\r
+StrCmp (\r
+  CONST CHAR16              *FirstString,\r
+  CONST CHAR16              *SecondString\r
+  )\r
+{\r
+  //\r
+  // ASSERT both strings are less long than PcdMaximumUnicodeStringLength\r
+  //\r
+  ASSERT (StrSize (FirstString) != 0);\r
+  ASSERT (StrSize (SecondString) != 0);\r
+\r
+  while ((*FirstString != L'\0') && (*FirstString == *SecondString)) {\r
+    FirstString++;\r
+    SecondString++;\r
+  }\r
+  return *FirstString - *SecondString;\r
+}\r
+\r
+UINT64\r
+SwapBytes64 (\r
+  UINT64                    Value\r
+  )\r
+{\r
+  return InternalMathSwapBytes64 (Value);\r
+}\r
+\r
+UINT64\r
+InternalMathSwapBytes64 (\r
+  UINT64                    Operand\r
+  )\r
+{\r
+  UINT64  LowerBytes;\r
+  UINT64  HigherBytes;\r
+\r
+  LowerBytes  = (UINT64) SwapBytes32 ((UINT32) Operand);\r
+  HigherBytes = (UINT64) SwapBytes32 ((UINT32) (Operand >> 32));\r
+\r
+  return (LowerBytes << 32 | HigherBytes);\r
+}\r
+\r
+RETURN_STATUS\r
+StrToIpv4Address (\r
+  CONST CHAR16       *String,\r
+  CHAR16             **EndPointer,\r
+  EFI_IPv4_ADDRESS       *Address,\r
+  UINT8              *PrefixLength\r
+  )\r
+{\r
+  RETURN_STATUS          Status;\r
+  UINTN                  AddressIndex;\r
+  UINTN                  Uintn;\r
+  EFI_IPv4_ADDRESS       LocalAddress;\r
+  UINT8                  LocalPrefixLength;\r
+  CHAR16                 *Pointer;\r
+\r
+  LocalPrefixLength = MAX_UINT8;\r
+  LocalAddress.Addr[0] = 0;\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
+  memcpy (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
+RETURN_STATUS\r
+StrToIpv6Address (\r
+  CONST CHAR16       *String,\r
+  CHAR16             **EndPointer,\r
+  EFI_IPv6_ADDRESS   *Address,\r
+  UINT8              *PrefixLength\r
+  )\r
+{\r
+  RETURN_STATUS          Status;\r
+  UINTN                  AddressIndex;\r
+  UINTN                  Uintn;\r
+  EFI_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
+        ASSERT (AddressIndex + 1 < ARRAY_SIZE (Address->Addr));\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
+  memcpy (&Address->Addr[0], &LocalAddress.Addr[0], CompressStart);\r
+  memset (&Address->Addr[CompressStart], 0,  ARRAY_SIZE (Address->Addr) - AddressIndex);\r
+  if (AddressIndex > CompressStart) {\r
+    memcpy (\r
+      &Address->Addr[CompressStart + ARRAY_SIZE (Address->Addr) - AddressIndex],\r
+      &LocalAddress.Addr[CompressStart],\r
+      AddressIndex - CompressStart\r
+      );\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
+RETURN_STATUS\r
+UnicodeStrToAsciiStrS (\r
+  CONST CHAR16              *Source,\r
+  CHAR8                     *Destination,\r
+  UINTN                     DestMax\r
+  )\r
+{\r
+  UINTN            SourceLen;\r
+\r
+  ASSERT (((UINTN) Source & BIT0) == 0);\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 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
+RETURN_STATUS\r
+StrCpyS (\r
+  CHAR16       *Destination,\r
+  UINTN        DestMax,\r
+  CONST CHAR16 *Source\r
+  )\r
+{\r
+  UINTN            SourceLen;\r
+\r
+  ASSERT (((UINTN) Destination & BIT0) == 0);\r
+  ASSERT (((UINTN) Source & BIT0) == 0);\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 RSIZE_MAX.\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 (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);\r
+\r
+  //\r
+  // The StrCpyS 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
+VOID *\r
+AllocateZeroPool (\r
+  UINTN  AllocationSize\r
+  )\r
+{\r
+  VOID * Memory;\r
+  Memory = malloc(AllocationSize);\r
+  ASSERT (Memory != NULL);\r
+  if (Memory == NULL) {\r
+    fprintf(stderr, "Not memory for malloc\n");\r
+  }\r
+  memset(Memory, 0, AllocationSize);\r
+  return Memory;\r
+}\r
+\r
+VOID *\r
+AllocatePool (\r
+  UINTN  AllocationSize\r
+  )\r
+{\r
+  return InternalAllocatePool (AllocationSize);\r
+}\r
+\r
+UINT16\r
+WriteUnaligned16 (\r
+  UINT16                    *Buffer,\r
+  UINT16                    Value\r
+  )\r
+{\r
+  ASSERT (Buffer != NULL);\r
+\r
+  return *Buffer = Value;\r
+}\r
+\r
+UINT16\r
+ReadUnaligned16 (\r
+  CONST UINT16              *Buffer\r
+  )\r
+{\r
+  ASSERT (Buffer != NULL);\r
+\r
+  return *Buffer;\r
+}\r
+/**\r
+  Return whether the integer string is a hex string.\r
+\r
+  @param Str             The integer string\r
+\r
+  @retval TRUE   Hex string\r
+  @retval FALSE  Decimal string\r
+\r
+**/\r
+BOOLEAN\r
+IsHexStr (\r
+   CHAR16   *Str\r
+  )\r
+{\r
+  //\r
+  // skip preceeding white space\r
+  //\r
+  while ((*Str != 0) && *Str == L' ') {\r
+    Str ++;\r
+  }\r
+  //\r
+  // skip preceeding zeros\r
+  //\r
+  while ((*Str != 0) && *Str == L'0') {\r
+    Str ++;\r
+  }\r
+\r
+  return (BOOLEAN) (*Str == L'x' || *Str == L'X');\r
+}\r
+\r
+/**\r
+\r
+  Convert integer string to uint.\r
+\r
+  @param Str             The integer string. If leading with "0x" or "0X", it's hexadecimal.\r
+\r
+  @return A UINTN value represented by Str\r
+\r
+**/\r
+UINTN\r
+Strtoi (\r
+   CHAR16  *Str\r
+  )\r
+{\r
+  if (IsHexStr (Str)) {\r
+    return StrHexToUintn (Str);\r
+  } else {\r
+    return StrDecimalToUintn (Str);\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Convert integer string to 64 bit data.\r
+\r
+  @param Str             The integer string. If leading with "0x" or "0X", it's hexadecimal.\r
+  @param Data            A pointer to the UINT64 value represented by Str\r
+\r
+**/\r
+VOID\r
+Strtoi64 (\r
+    CHAR16  *Str,\r
+   UINT64  *Data\r
+  )\r
+{\r
+  if (IsHexStr (Str)) {\r
+    *Data = StrHexToUint64 (Str);\r
+  } else {\r
+    *Data = StrDecimalToUint64 (Str);\r
+  }\r
+}\r
+\r
+/**\r
+  Converts a Unicode string to ASCII string.\r
+\r
+  @param Str             The equivalent Unicode string\r
+  @param AsciiStr        On input, it points to destination ASCII string buffer; on output, it points\r
+                         to the next ASCII string next to it\r
+\r
+**/\r
+VOID\r
+StrToAscii (\r
+       CHAR16 *Str,\r
+    CHAR8  **AsciiStr\r
+  )\r
+{\r
+  CHAR8 *Dest;\r
+\r
+  Dest = *AsciiStr;\r
+  while (!IS_NULL (*Str)) {\r
+    *(Dest++) = (CHAR8) *(Str++);\r
+  }\r
+  *Dest = 0;\r
+\r
+  //\r
+  // Return the string next to it\r
+  //\r
+  *AsciiStr = Dest + 1;\r
+}\r
+\r
+/**\r
+  Gets current sub-string from a string list, before return\r
+  the list header is moved to next sub-string. The sub-string is separated\r
+  by the specified character. For example, the separator is ',', the string\r
+  list is "2,0,3", it returns "2", the remain list move to "0,3"\r
+\r
+  @param  List        A string list separated by the specified separator\r
+  @param  Separator   The separator character\r
+\r
+  @return A pointer to the current sub-string\r
+\r
+**/\r
+CHAR16 *\r
+SplitStr (\r
+    CHAR16 **List,\r
+       CHAR16 Separator\r
+  )\r
+{\r
+  CHAR16  *Str;\r
+  CHAR16  *ReturnStr;\r
+\r
+  Str = *List;\r
+  ReturnStr = Str;\r
+\r
+  if (IS_NULL (*Str)) {\r
+    return ReturnStr;\r
+  }\r
+\r
+  //\r
+  // Find first occurrence of the separator\r
+  //\r
+  while (!IS_NULL (*Str)) {\r
+    if (*Str == Separator) {\r
+      break;\r
+    }\r
+    Str++;\r
+  }\r
+\r
+  if (*Str == Separator) {\r
+    //\r
+    // Find a sub-string, terminate it\r
+    //\r
+    *Str = L'\0';\r
+    Str++;\r
+  }\r
+\r
+  //\r
+  // Move to next sub-string\r
+  //\r
+  *List = Str;\r
+  return ReturnStr;\r
+}\r
+\r