]> 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 aa891152bf3eca563e21475bbd7c2e9ea55a2838..90cc578e619d3250a317261d3021276ad154b466 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Common basic Library Functions\r
 \r
-Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 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
@@ -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
@@ -638,12 +646,22 @@ Returns:
       //\r
       RootPath = getcwd (NULL, 0);\r
       if (RootPath != NULL) {\r
-        strcat (mCommonLibFullPath, RootPath);\r
+        if (strlen (mCommonLibFullPath) + strlen (RootPath) > MAX_LONG_FILE_PATH - 1) {\r
+          Error (NULL, 0, 2000, "Invalid parameter", "RootPath is too long!");\r
+          free (RootPath);\r
+          return NULL;\r
+        }\r
+        strncat (mCommonLibFullPath, RootPath, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);\r
         if (FileName[0] != '\\' && FileName[0] != '/') {\r
+          if (strlen (mCommonLibFullPath) + 1 > MAX_LONG_FILE_PATH - 1) {\r
+            Error (NULL, 0, 2000, "Invalid parameter", "RootPath is too long!");\r
+            free (RootPath);\r
+            return NULL;\r
+          }\r
           //\r
           // Attach directory separator\r
           //\r
-          strcat (mCommonLibFullPath, "\\");\r
+          strncat (mCommonLibFullPath, "\\", MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);\r
         }\r
         free (RootPath);\r
       }\r
@@ -652,7 +670,11 @@ Returns:
     //\r
     // Construct the full file path\r
     //\r
-    strcat (mCommonLibFullPath, FileName);\r
+    if (strlen (mCommonLibFullPath) + strlen (FileName) > MAX_LONG_FILE_PATH - 1) {\r
+      Error (NULL, 0, 2000, "Invalid parameter", "FileName %s is too long!", FileName);\r
+      return NULL;\r
+    }\r
+    strncat (mCommonLibFullPath, FileName, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);\r
     \r
     //\r
     // Convert directory separator '/' to '\\'\r
@@ -669,7 +691,15 @@ Returns:
     //\r
     if ((PathPointer = strstr (mCommonLibFullPath, ":\\\\")) != NULL) {\r
       *(PathPointer + 2) = '\0';\r
-      strcat (mCommonLibFullPath, PathPointer + 3);\r
+      strncat (mCommonLibFullPath, PathPointer + 3, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);\r
+    }\r
+    \r
+    //\r
+    // Convert ".\\" to "", because it doesn't work with WINDOWS_EXTENSION_PATH.\r
+    //\r
+    while ((PathPointer = strstr (mCommonLibFullPath, ".\\")) != NULL) {\r
+      *PathPointer = '\0';\r
+      strncat (mCommonLibFullPath, PathPointer + 2, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);\r
     }\r
         \r
     //\r
@@ -677,9 +707,9 @@ Returns:
     //\r
     while ((PathPointer = strstr (mCommonLibFullPath, "\\.\\")) != NULL) {\r
       *PathPointer = '\0';\r
-      strcat (mCommonLibFullPath, PathPointer + 2);\r
+      strncat (mCommonLibFullPath, PathPointer + 2, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);\r
     }\r
-    \r
+\r
     //\r
     // Convert "\\..\\" to last directory, because it doesn't work with WINDOWS_EXTENSION_PATH.\r
     //\r
@@ -694,7 +724,7 @@ Returns:
         // Skip one directory\r
         //\r
         *PathPointer = '\0';\r
-        strcat (mCommonLibFullPath, NextPointer);\r
+        strncat (mCommonLibFullPath, NextPointer, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);\r
       } else {\r
         //\r
         // No directory is found. Just break.\r
@@ -709,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