/** @file\r
Common basic Library Functions\r
\r
-Copyright (c) 2004 - 2016, 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
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+Copyright (c) 2004 - 2018, 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
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
\r
**/\r
\r
#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
\r
Returns:\r
= 0 if Guid1 == Guid2\r
- != 0 if Guid1 != Guid2 \r
+ != 0 if Guid1 != Guid2\r
\r
--*/\r
{\r
\r
Routine Description:\r
\r
- This function opens a file and reads it into a memory buffer. The function \r
+ This function opens a file and reads it into a memory buffer. The function\r
will allocate the memory buffer and returns the size of the buffer.\r
\r
Arguments:\r
IN UINTN Size\r
)\r
/*++\r
- \r
+\r
Routine Description:\r
\r
This function calculates the value needed for a valid UINT8 checksum\r
IN UINTN Size\r
)\r
/*++\r
- \r
+\r
Routine Description::\r
\r
This function calculates the UINT8 sum for the requested region.\r
IN UINTN Size\r
)\r
/*++\r
- \r
+\r
Routine Description::\r
\r
This function calculates the value needed for a valid UINT16 checksum\r
IN UINTN Size\r
)\r
/*++\r
- \r
+\r
Routine Description:\r
\r
This function calculates the UINT16 sum for the requested region.\r
EFI_SUCCESS The GUID was printed.\r
EFI_INVALID_PARAMETER The input was NULL.\r
EFI_BUFFER_TOO_SMALL The input buffer was not big enough\r
- \r
+\r
--*/\r
{\r
if (Guid == NULL) {\r
#define WINDOWS_UNC_EXTENSION_PATH "\\\\?\\UNC"\r
\r
//\r
-// Global data to store full file path. It is not required to be free. \r
+// Global data to store full file path. It is not required to be free.\r
//\r
CHAR8 mCommonLibFullPath[MAX_LONG_FILE_PATH];\r
\r
/*++\r
\r
Routine Description:\r
- Convert FileName to the long file path, which can support larger than 260 length. \r
+ Convert FileName to the long file path, which can support larger than 260 length.\r
\r
Arguments:\r
- FileName - FileName. \r
+ FileName - FileName.\r
\r
Returns:\r
LongFilePath A pointer to the converted long file path.\r
- \r
+\r
--*/\r
{\r
#ifdef __GNUC__\r
//\r
- // __GNUC__ may not be good way to differentiate unix and windows. Need more investigation here. \r
- // unix has no limitation on file path. Just return FileName. \r
+ // __GNUC__ may not be good way to differentiate unix and windows. Need more investigation here.\r
+ // unix has no limitation on file path. Just return FileName.\r
//\r
return FileName;\r
#else\r
CHAR8 *RootPath;\r
CHAR8 *PathPointer;\r
CHAR8 *NextPointer;\r
- \r
+\r
PathPointer = (CHAR8 *) FileName;\r
- \r
+\r
if (FileName != NULL) {\r
//\r
- // Add the extension string first to support long file path. \r
+ // Add the extension string first to support long file path.\r
//\r
mCommonLibFullPath[0] = 0;\r
strcpy (mCommonLibFullPath, WINDOWS_EXTENSION_PATH);\r
FileName ++;\r
} else if (strlen (FileName) < 3 || FileName[1] != ':' || (FileName[2] != '\\' && FileName[2] != '/')) {\r
//\r
- // Relative file path. Convert it to absolute path. \r
+ // Relative file path. Convert it to absolute path.\r
//\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
return NULL;\r
}\r
strncat (mCommonLibFullPath, FileName, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);\r
- \r
+\r
//\r
// Convert directory separator '/' to '\\'\r
//\r
*PathPointer = '\\';\r
}\r
} while (*PathPointer ++ != '\0');\r
- \r
+\r
//\r
// Convert ":\\\\" to ":\\", because it doesn't work with WINDOWS_EXTENSION_PATH.\r
//\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
//\r
// Convert ".\\" to "", because it doesn't work with WINDOWS_EXTENSION_PATH.\r
//\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 "\\", because it doesn't work with WINDOWS_EXTENSION_PATH.\r
//\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
// 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
break;\r
}\r
}\r
- \r
+\r
PathPointer = mCommonLibFullPath;\r
}\r
- \r
+\r
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
+/**\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
+ UINT64.\r
+\r
+ This function outputs a value of type UINT64 by interpreting the contents of\r
+ the Unicode string specified by String as a hexadecimal number. The format of\r
+ the input Unicode string String is:\r
+\r
+ [spaces][zeros][x][hexadecimal digits].\r
+\r
+ The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
+ The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.\r
+ If "x" appears in the input string, it must be prefixed with at least one 0.\r
+ The function will ignore the pad space, which includes spaces or tab\r
+ characters, before [zeros], [x] or [hexadecimal digit]. The running zero\r
+ before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts\r
+ after [x] or the first valid hexadecimal digit. Then, the function stops at\r
+ the first character that is a not a valid hexadecimal character or NULL,\r
+ whichever one comes first.\r
+\r
+ If String is NULL, then ASSERT().\r
+ If Data is NULL, then ASSERT().\r
+ If String is not aligned in a 16-bit boundary, then ASSERT().\r
+ If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
+ PcdMaximumUnicodeStringLength Unicode characters, not including the\r
+ Null-terminator, then ASSERT().\r
+\r
+ If String has no valid hexadecimal digits in the above format, then 0 is\r
+ stored at the location pointed to by Data.\r
+ If the number represented by String exceeds the range defined by UINT64, then\r
+ MAX_UINT64 is stored at the location pointed to by Data.\r
+\r
+ If EndPointer is not NULL, a pointer to the character that stopped the scan\r
+ is stored at the location pointed to by EndPointer. If String has no valid\r
+ hexadecimal digits right after the optional pad spaces, the value of String\r
+ is stored at the location pointed to by EndPointer.\r
+\r
+ @param String Pointer to a Null-terminated Unicode string.\r
+ @param EndPointer Pointer to character that stops scan.\r
+ @param Data Pointer to the converted value.\r
+\r
+ @retval RETURN_SUCCESS Value is translated from String.\r
+ @retval RETURN_INVALID_PARAMETER If String is NULL.\r
+ If Data is NULL.\r
+ If PcdMaximumUnicodeStringLength is not\r
+ zero, and String contains more than\r
+ PcdMaximumUnicodeStringLength Unicode\r
+ characters, not including the\r
+ Null-terminator.\r
+ @retval RETURN_UNSUPPORTED If the number represented by String exceeds\r
+ the range defined by UINT64.\r
+\r
+**/\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
+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
+ UINT64 Uint64;\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 = StrDecimalToUint64S ((CONST CHAR16 *) Pointer, &Pointer, &Uint64);\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 (Uint64 > 32) {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+ LocalPrefixLength = (UINT8) Uint64;\r
+ } else {\r
+ //\r
+ // It's D.\r
+ //\r
+ if (Uint64 > MAX_UINT8) {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+ LocalAddress.Addr[AddressIndex] = (UINT8) Uint64;\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
+ UINT64 Uint64;\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 = StrHexToUint64S (Pointer, &End, &Uint64);\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
+ // Uint64 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) Uint64 >> 8);\r
+ LocalAddress.Addr[AddressIndex + 1] = (UINT8) Uint64;\r
+ AddressIndex += 2;\r
+ } else {\r
+ //\r
+ // Get P, then exit the loop.\r
+ //\r
+ Status = StrDecimalToUint64S (Pointer, &End, &Uint64);\r
+ if (RETURN_ERROR (Status) || End == Pointer || Uint64 > 128) {\r
+ //\r
+ // Prefix length should not exceed 128.\r
+ //\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+ LocalPrefixLength = (UINT8) Uint64;\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
+ if (AddressIndex > CompressStart) {\r
+ memset (&Address->Addr[CompressStart], 0, ARRAY_SIZE (Address->Addr) - AddressIndex);\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 (UINTN)StrHexToUint64 (Str);\r
+ } else {\r
+ return (UINTN)StrDecimalToUint64 (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