+/**\r
+ Returns the first occurance of a Null-terminated Unicode sub-string \r
+ in a Null-terminated Unicode string.\r
+\r
+ This function scans the contents of the Null-terminated Unicode string \r
+ specified by String and returns the first occurrence of SearchString. \r
+ If SearchString is not found in String, then NULL is returned. If \r
+ the length of SearchString is zero, then String is \r
+ returned.\r
+ \r
+ If String is NULL, then ASSERT().\r
+ If String is not aligned on a 16-bit boundary, then ASSERT().\r
+ If SearchString is NULL, then ASSERT().\r
+ If SearchString is not aligned on a 16-bit boundary, then ASSERT().\r
+\r
+ If PcdMaximumUnicodeStringLength is not zero, and SearchString \r
+ or String contains more than PcdMaximumUnicodeStringLength Unicode \r
+ characters not including the Null-terminator, then ASSERT().\r
+\r
+ @param String Pointer to a Null-terminated Unicode string.\r
+ @param SearchString Pointer to a Null-terminated Unicode string to search for.\r
+\r
+ @retval NULL If the SearchString does not appear in String.\r
+ @retval !NULL If there is a match.\r
+\r
+**/\r
+CHAR16 *\r
+EFIAPI\r
+StrStr (\r
+ IN CONST CHAR16 *String,\r
+ IN CONST CHAR16 *SearchString\r
+ )\r
+{\r
+ CONST CHAR16 *FirstMatch;\r
+ CONST CHAR16 *SearchStringTmp;\r
+\r
+ ASSERT (String != NULL);\r
+ ASSERT (((UINTN) String & 0x01) == 0);\r
+ ASSERT (SearchString != NULL);\r
+ ASSERT (((UINTN) SearchString & 0x01) == 0);\r
+\r
+ //\r
+ // If PcdMaximumUnicodeStringLength is not zero,\r
+ // length of String should not more than PcdMaximumUnicodeStringLength\r
+ //\r
+ if (PcdGet32 (PcdMaximumUnicodeStringLength) != 0) {\r
+ ASSERT (StrLen (String) < PcdGet32 (PcdMaximumUnicodeStringLength));\r
+ }\r
+\r
+ //\r
+ // If PcdMaximumUnicodeStringLength is not zero,\r
+ // length of SearchString should not more than PcdMaximumUnicodeStringLength\r
+ //\r
+ if (PcdGet32 (PcdMaximumUnicodeStringLength) != 0) {\r
+ ASSERT (StrLen (SearchString) < PcdGet32 (PcdMaximumAsciiStringLength));\r
+ }\r
+\r
+ while (*String != '\0') {\r
+ SearchStringTmp = SearchString;\r
+ FirstMatch = String;\r
+ \r
+ while ((*String == *SearchStringTmp) \r
+ && (*SearchStringTmp != '\0') \r
+ && (*String != '\0')) {\r
+ String++;\r
+ SearchStringTmp++;\r
+ } \r
+ \r
+ if (*SearchStringTmp == '\0') {\r
+ return (CHAR16 *) FirstMatch;\r
+ }\r
+\r
+ if (SearchStringTmp == SearchString) {\r
+ //\r
+ // If no character from SearchString match,\r
+ // move the pointer to the String under search\r
+ // by one character.\r
+ //\r
+ String++;\r
+ }\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Check if a Unicode character is a decimal character.\r
+\r
+ This internal function checks if a Unicode character is a \r
+ decimal character. The valid decimal character is from\r
+ L'0' to L'9'.\r
+\r
+\r
+ @param Char The character to check against.\r
+\r
+ @retval TRUE If the Char is a decmial character.\r
+ @retval FALSE Otherwise.\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+InternalIsDecimalDigitCharacter (\r
+ IN CHAR16 Char\r
+ )\r
+{\r
+ return (BOOLEAN) (Char >= L'0' && Char <= L'9');\r
+}\r
+\r
+/**\r
+ Convert a Unicode character to upper case only if \r
+ it maps to a valid small-case ASCII character.\r
+\r
+ This internal function only deal with Unicode character\r
+ which maps to a valid small-case ASII character, i.e.\r
+ L'a' to L'z'. For other Unicode character, the input character\r
+ is returned directly.\r
+\r
+\r
+ @param Char The character to convert.\r
+\r
+ @retval LowerCharacter If the Char is with range L'a' to L'z'.\r
+ @retval Unchanged Otherwise.\r
+\r
+**/\r
+STATIC\r
+CHAR16\r
+InternalCharToUpper (\r
+ IN 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
+/**\r
+ Convert a Unicode character to numerical value.\r
+\r
+ This internal function only deal with Unicode character\r
+ which maps to a valid hexadecimal ASII character, i.e.\r
+ L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other \r
+ Unicode character, the value returned does not make sense.\r
+\r
+ @param Char The character to convert.\r
+\r
+ @retval UINTN The numerical value converted.\r
+\r
+**/\r
+STATIC\r
+UINTN\r
+InternalHexCharToUintn (\r
+ IN CHAR16 Char\r
+ )\r
+{\r
+ if (InternalIsDecimalDigitCharacter (Char)) {\r
+ return Char - L'0';\r
+ }\r
+\r
+ return (UINTN) (10 + InternalCharToUpper (Char) - L'A');\r
+}\r
+\r
+/**\r
+ Check if a Unicode character is a hexadecimal character.\r
+\r
+ This internal function checks if a Unicode character is a \r
+ decimal character. The valid hexadecimal character is \r
+ L'0' to L'9', L'a' to L'f', or L'A' to L'F'.\r
+\r
+\r
+ @param Char The character to check against.\r
+\r
+ @retval TRUE If the Char is a hexadecmial character.\r
+ @retval FALSE Otherwise.\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+InternalIsHexaDecimalDigitCharacter (\r
+ IN 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
+/**\r
+ Convert a Null-terminated Unicode decimal string to a value of \r
+ type UINTN.\r
+\r
+ This function returns a value of type UINTN by interpreting the contents \r
+ of the Unicode string specified by String as a decimal number. The format \r
+ of the input Unicode string String is:\r
+ \r
+ [spaces] [decimal digits].\r
+ \r
+ The valid decimal digit character is in the range [0-9]. The \r
+ function will ignore the pad space, which includes spaces or \r
+ tab characters, before [decimal digits]. The running zero in the \r
+ beginning of [decimal digits] will be ignored. Then, the function \r
+ stops at the first character that is a not a valid decimal character \r
+ or a Null-terminator, whichever one comes first. \r
+ \r
+ If String is NULL, then ASSERT().\r
+ If String is not aligned in a 16-bit boundary, then ASSERT(). \r
+ If String has only pad spaces, then 0 is returned.\r
+ If String has no pad spaces or valid decimal digits, \r
+ then 0 is returned.\r
+ If the number represented by String overflows according \r
+ to the range defined by UINTN, then ASSERT().\r
+ \r
+ If PcdMaximumUnicodeStringLength is not zero, and String contains \r
+ more than PcdMaximumUnicodeStringLength Unicode characters not including \r
+ the Null-terminator, then ASSERT().\r
+\r
+ @param String Pointer to a Null-terminated Unicode string.\r
+\r
+ @retval UINTN \r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+StrDecimalToUintn (\r
+ IN CONST CHAR16 *String\r
+ )\r
+{\r
+ UINTN Result;\r
+ \r
+ ASSERT (String != NULL);\r
+ ASSERT (((UINTN) String & 0x01) == 0);\r
+ ASSERT (StrLen (String) < PcdGet32 (PcdMaximumUnicodeStringLength));\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
+ Result = 0;\r
+\r
+ while (InternalIsDecimalDigitCharacter (*String)) {\r
+ //\r
+ // If the number represented by String overflows according \r
+ // to the range defined by UINTN, then ASSERT().\r
+ //\r
+ ASSERT ((Result < QUIENT_MAX_UINTN_DIVIDED_BY_10) ||\r
+ ((Result == QUIENT_MAX_UINTN_DIVIDED_BY_10) &&\r
+ (*String - L'0') <= REMINDER_MAX_UINTN_DIVIDED_BY_10)\r
+ );\r
+\r
+ Result = Result * 10 + (*String - L'0');\r
+ String++;\r
+ }\r
+ \r
+ return Result;\r
+}\r
+\r
+\r
+/**\r
+ Convert a Null-terminated Unicode decimal string to a value of \r
+ type UINT64.\r
+\r
+ This function returns a value of type UINT64 by interpreting the contents \r
+ of the Unicode string specified by String as a decimal number. The format \r
+ of the input Unicode string String is:\r
+ \r
+ [spaces] [decimal digits].\r
+ \r
+ The valid decimal digit character is in the range [0-9]. The \r
+ function will ignore the pad space, which includes spaces or \r
+ tab characters, before [decimal digits]. The running zero in the \r
+ beginning of [decimal digits] will be ignored. Then, the function \r
+ stops at the first character that is a not a valid decimal character \r
+ or a Null-terminator, whichever one comes first. \r
+ \r
+ If String is NULL, then ASSERT().\r
+ If String is not aligned in a 16-bit boundary, then ASSERT(). \r
+ If String has only pad spaces, then 0 is returned.\r
+ If String has no pad spaces or valid decimal digits, \r
+ then 0 is returned.\r
+ If the number represented by String overflows according \r
+ to the range defined by UINT64, then ASSERT().\r
+ \r
+ If PcdMaximumUnicodeStringLength is not zero, and String contains \r
+ more than PcdMaximumUnicodeStringLength Unicode characters not including \r
+ the Null-terminator, then ASSERT().\r
+\r
+ @param String Pointer to a Null-terminated Unicode string.\r
+\r
+ @retval UINT64 \r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+StrDecimalToUint64 (\r
+ IN CONST CHAR16 *String\r
+ )\r
+{\r
+ UINT64 Result;\r
+ \r
+ ASSERT (String != NULL);\r
+ ASSERT (((UINTN) String & 0x01) == 0);\r
+ ASSERT (StrLen (String) < PcdGet32 (PcdMaximumUnicodeStringLength));\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
+ Result = 0;\r
+\r
+ while (InternalIsDecimalDigitCharacter (*String)) {\r
+ //\r
+ // If the number represented by String overflows according \r
+ // to the range defined by UINTN, then ASSERT().\r
+ //\r
+ ASSERT ((Result < QUIENT_MAX_UINT64_DIVIDED_BY_10) || \r
+ ((Result == QUIENT_MAX_UINT64_DIVIDED_BY_10) && \r
+ (*String - L'0') <= REMINDER_MAX_UINT64_DIVIDED_BY_10)\r
+ );\r
+\r
+ Result = MultU64x32 (Result, 10) + (*String - L'0');\r
+ String++;\r
+ }\r
+ \r
+ return Result;\r
+}\r
+\r
+/**\r
+ Convert a Null-terminated Unicode hexadecimal string to a value of type UINTN.\r
+\r
+ This function returns a value of type UINTN by interpreting the contents \r
+ of the Unicode string specified by String as a hexadecimal number. \r
+ The format of 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 characters, \r
+ before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or \r
+ [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the \r
+ first valid hexadecimal digit. Then, the function stops at the first character that is \r
+ a not a valid hexadecimal character or NULL, whichever one comes first.\r
+\r
+ If String is NULL, then ASSERT().\r
+ If String is not aligned in a 16-bit boundary, then ASSERT().\r
+ If String has only pad spaces, then zero is returned.\r
+ If String has no leading pad spaces, leading zeros or valid hexadecimal digits, \r
+ then zero is returned.\r
+ If the number represented by String overflows according to the range defined by \r
+ UINTN, then ASSERT().\r
+\r
+ If PcdMaximumUnicodeStringLength is not zero, and String contains more than \r
+ PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, \r
+ then ASSERT().\r
+\r
+ @param String Pointer to a Null-terminated Unicode string.\r
+\r
+ @retval UINTN\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+StrHexToUintn (\r
+ IN CONST CHAR16 *String\r
+ )\r
+{\r
+ UINTN Result;\r
+\r
+ ASSERT (String != NULL);\r
+ ASSERT (((UINTN) String & 0x01) == 0);\r
+ ASSERT (StrLen (String) < PcdGet32 (PcdMaximumUnicodeStringLength));\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
+ ASSERT (*(String - 1) == L'0');\r
+ if (*(String - 1) != L'0') {\r
+ return 0;\r
+ }\r
+ //\r
+ // Skip the 'X'\r
+ //\r
+ String++;\r
+ }\r
+\r
+ Result = 0;\r
+ \r
+ while (InternalIsHexaDecimalDigitCharacter (*String)) {\r
+ //\r
+ // If the Hex Number represented by String overflows according \r
+ // to the range defined by UINTN, then ASSERT().\r
+ //\r
+ ASSERT ((Result < QUIENT_MAX_UINTN_DIVIDED_BY_16) ||\r
+ ((Result == QUIENT_MAX_UINTN_DIVIDED_BY_16) && \r
+ (InternalHexCharToUintn (*String) <= REMINDER_MAX_UINTN_DIVIDED_BY_16))\r
+ );\r
+\r
+ Result = (Result << 4) + InternalHexCharToUintn (*String);\r
+ String++;\r
+ }\r
+\r
+ return Result;\r
+}\r
+\r
+\r
+/**\r
+ Convert a Null-terminated Unicode hexadecimal string to a value of type UINT64.\r
+\r
+ This function returns a value of type UINT64 by interpreting the contents \r
+ of the Unicode string specified by String as a hexadecimal number. \r
+ The format of 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 characters, \r
+ before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or \r
+ [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the \r
+ first valid hexadecimal digit. Then, the function stops at the first character that is \r
+ a not a valid hexadecimal character or NULL, whichever one comes first.\r
+\r
+ If String is NULL, then ASSERT().\r
+ If String is not aligned in a 16-bit boundary, then ASSERT().\r
+ If String has only pad spaces, then zero is returned.\r
+ If String has no leading pad spaces, leading zeros or valid hexadecimal digits, \r
+ then zero is returned.\r
+ If the number represented by String overflows according to the range defined by \r
+ UINT64, then ASSERT().\r
+\r
+ If PcdMaximumUnicodeStringLength is not zero, and String contains more than \r
+ PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, \r
+ then ASSERT().\r
+\r
+ @param String Pointer to a Null-terminated Unicode string.\r
+\r
+ @retval UINT64\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+StrHexToUint64 (\r
+ IN CONST CHAR16 *String\r
+ )\r
+{\r
+ UINT64 Result;\r
+\r
+ ASSERT (String != NULL);\r
+ ASSERT (((UINTN) String & 0x01) == 0);\r
+ ASSERT (StrLen (String) < PcdGet32 (PcdMaximumUnicodeStringLength));\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
+ ASSERT (*(String - 1) == L'0');\r
+ if (*(String - 1) != L'0') {\r
+ return 0;\r
+ }\r
+ //\r
+ // Skip the 'X'\r
+ //\r
+ String++;\r
+ }\r
+\r
+ Result = 0;\r
+ \r
+ while (InternalIsHexaDecimalDigitCharacter (*String)) {\r
+ //\r
+ // If the Hex Number represented by String overflows according \r
+ // to the range defined by UINTN, then ASSERT().\r
+ //\r
+ ASSERT ((Result < QUIENT_MAX_UINT64_DIVIDED_BY_16)|| \r
+ ((Result == QUIENT_MAX_UINT64_DIVIDED_BY_16) && \r
+ (InternalHexCharToUintn (*String) <= REMINDER_MAX_UINT64_DIVIDED_BY_16))\r
+ );\r
+\r
+ Result = LShiftU64 (Result, 4);\r
+ Result = Result + InternalHexCharToUintn (*String);\r
+ String++;\r
+ }\r
+\r
+ return Result;\r
+}\r
+\r
+/**\r
+ Check if a ASCII character is a decimal character.\r
+\r
+ This internal function checks if a Unicode character is a \r
+ decimal character. The valid decimal character is from\r
+ '0' to '9'.\r
+\r
+ @param Char The character to check against.\r
+\r
+ @retval TRUE If the Char is a decmial character.\r
+ @retval FALSE Otherwise.\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+InternalAsciiIsDecimalDigitCharacter (\r
+ IN CHAR8 Char\r
+ )\r
+{\r
+ return (BOOLEAN) (Char >= '0' && Char <= '9');\r
+}\r
+\r
+/**\r
+ Check if a ASCII character is a hexadecimal character.\r
+\r
+ This internal function checks if a ASCII character is a \r
+ decimal character. The valid hexadecimal character is \r
+ L'0' to L'9', L'a' to L'f', or L'A' to L'F'.\r
+\r
+\r
+ @param Char The character to check against.\r
+\r
+ @retval TRUE If the Char is a hexadecmial character.\r
+ @retval FALSE Otherwise.\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+InternalAsciiIsHexaDecimalDigitCharacter (\r
+ IN CHAR8 Char\r
+ )\r
+{\r
+\r
+ return (BOOLEAN) (InternalAsciiIsDecimalDigitCharacter (Char) ||\r
+ (Char >= 'A' && Char <= 'F') ||\r
+ (Char >= 'a' && Char <= 'f'));\r
+}\r
+\r
+/**\r
+ Convert a Null-terminated Unicode string to a Null-terminated \r
+ ASCII string and returns the ASCII string.\r
+ \r
+ This function converts the content of the Unicode string Source \r
+ to the ASCII string Destination by copying the lower 8 bits of \r
+ each Unicode character. It returns Destination. The function terminates \r
+ the ASCII string Destination by appending a Null-terminator character \r
+ at the end. The caller is responsible to make sure Destination points \r
+ to a buffer with size equal or greater than (StrLen (Source) + 1) in bytes.\r
+\r
+ If Destination is NULL, then ASSERT().\r
+ If Source is NULL, then ASSERT().\r
+ If Source is not aligned on a 16-bit boundary, then ASSERT().\r
+ If Source and Destination overlap, then ASSERT().\r
+\r
+ If any Unicode characters in Source contain non-zero value in \r
+ the upper 8 bits, then ASSERT().\r
+ \r
+ If PcdMaximumUnicodeStringLength is not zero, and Source contains \r
+ more than PcdMaximumUnicodeStringLength Unicode characters not including \r
+ the Null-terminator, then ASSERT().\r
+ \r
+ If PcdMaximumAsciiStringLength is not zero, and Source contains more \r
+ than PcdMaximumAsciiStringLength Unicode characters not including the \r
+ Null-terminator, then ASSERT().\r
+\r
+ @param Source Pointer to a Null-terminated Unicode string.\r
+ @param Destination Pointer to a Null-terminated ASCII string.\r
+\r
+ @reture Destination\r
+\r
+**/\r
+CHAR8 *\r
+EFIAPI\r
+UnicodeStrToAsciiStr (\r
+ IN CONST CHAR16 *Source,\r
+ OUT CHAR8 *Destination\r
+ )\r
+{\r
+ ASSERT (Destination != NULL);\r
+ ASSERT (Source != NULL);\r
+ ASSERT (((UINTN) Source & 0x01) == 0);\r
+\r
+ //\r
+ // Source and Destination should not overlap\r
+ //\r
+ ASSERT ((UINTN) ((CHAR16 *) Destination - Source) > StrLen (Source));\r
+ ASSERT ((UINTN) ((CHAR8 *) Source - Destination) > StrLen (Source));\r
+\r
+ //\r
+ // If PcdMaximumUnicodeStringLength is not zero,\r
+ // length of Source should not more than PcdMaximumUnicodeStringLength\r
+ //\r
+ if (PcdGet32 (PcdMaximumUnicodeStringLength) != 0) {\r
+ ASSERT (StrLen (Source) < PcdGet32 (PcdMaximumUnicodeStringLength));\r
+ }\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
+\r
+ *Destination = '\0';\r
+ \r
+ return Destination;\r
+}\r
+\r
+\r