/** @file\r
Print Library internal worker functions.\r
\r
- Copyright (c) 2006 - 2011, 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) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "PrintLibInternal.h"\r
\r
-#define WARNING_STATUS_NUMBER 4\r
-#define ERROR_STATUS_NUMBER 24\r
+#define WARNING_STATUS_NUMBER 5\r
+#define ERROR_STATUS_NUMBER 33\r
+\r
+//\r
+// Safe print checks\r
+//\r
+#define RSIZE_MAX (PcdGet32 (PcdMaximumUnicodeStringLength))\r
+#define ASCII_RSIZE_MAX (PcdGet32 (PcdMaximumAsciiStringLength))\r
+\r
+#define SAFE_PRINT_CONSTRAINT_CHECK(Expression, RetVal) \\r
+ do { \\r
+ ASSERT (Expression); \\r
+ if (!(Expression)) { \\r
+ return RetVal; \\r
+ } \\r
+ } while (FALSE)\r
\r
GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};\r
\r
-GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mStatusString[] = {\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 * CONST mStatusString[] = {\r
"Success", // RETURN_SUCCESS = 0\r
"Warning Unknown Glyph", // RETURN_WARN_UNKNOWN_GLYPH = 1\r
"Warning Delete Failure", // RETURN_WARN_DELETE_FAILURE = 2\r
"Warning Write Failure", // RETURN_WARN_WRITE_FAILURE = 3\r
"Warning Buffer Too Small", // RETURN_WARN_BUFFER_TOO_SMALL = 4\r
+ "Warning Stale Data", // RETURN_WARN_STALE_DATA = 5\r
"Load Error", // RETURN_LOAD_ERROR = 1 | MAX_BIT\r
"Invalid Parameter", // RETURN_INVALID_PARAMETER = 2 | MAX_BIT\r
"Unsupported", // RETURN_UNSUPPORTED = 3 | MAX_BIT\r
"Aborted", // RETURN_ABORTED = 21 | MAX_BIT\r
"ICMP Error", // RETURN_ICMP_ERROR = 22 | MAX_BIT\r
"TFTP Error", // RETURN_TFTP_ERROR = 23 | MAX_BIT\r
- "Protocol Error" // RETURN_PROTOCOL_ERROR = 24 | MAX_BIT\r
+ "Protocol Error", // RETURN_PROTOCOL_ERROR = 24 | MAX_BIT\r
+ "Incompatible Version", // RETURN_INCOMPATIBLE_VERSION = 25 | MAX_BIT\r
+ "Security Violation", // RETURN_SECURITY_VIOLATION = 26 | MAX_BIT\r
+ "CRC Error", // RETURN_CRC_ERROR = 27 | MAX_BIT\r
+ "End of Media", // RETURN_END_OF_MEDIA = 28 | MAX_BIT\r
+ "Reserved (29)", // RESERVED = 29 | MAX_BIT\r
+ "Reserved (30)", // RESERVED = 30 | MAX_BIT\r
+ "End of File", // RETURN_END_OF_FILE = 31 | MAX_BIT\r
+ "Invalid Language", // RETURN_INVALID_LANGUAGE = 32 | MAX_BIT\r
+ "Compromised Data" // RETURN_COMPROMISED_DATA = 33 | MAX_BIT\r
};\r
\r
\r
\r
@param Buffer The buffer to place the Unicode or ASCII string.\r
@param EndBuffer The end of the input Buffer. No characters will be\r
- placed after that. \r
+ placed after that.\r
@param Length The count of character to be placed into Buffer.\r
(Negative value indicates no buffer fill.)\r
@param Character The character to be placed into Buffer.\r
)\r
{\r
INTN Index;\r
- \r
+\r
for (Index = 0; Index < Length && Buffer < EndBuffer; Index++) {\r
*Buffer = (CHAR8) Character;\r
if (Increment != 1) {\r
**/\r
CHAR8 *\r
BasePrintLibValueToString (\r
- IN OUT CHAR8 *Buffer, \r
- IN INT64 Value, \r
+ IN OUT CHAR8 *Buffer,\r
+ IN INT64 Value,\r
IN UINTN Radix\r
)\r
{\r
\r
/**\r
Internal function that converts a decimal value to a Null-terminated string.\r
- \r
- Converts the decimal number specified by Value to a Null-terminated \r
+\r
+ Converts the decimal number specified by Value to a Null-terminated\r
string specified by Buffer containing at most Width characters.\r
If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.\r
The total number of characters placed in Buffer is returned.\r
If the conversion contains more than Width characters, then only the first\r
- Width characters are returned, and the total number of characters \r
+ Width characters are returned, and the total number of characters\r
required to perform the conversion is returned.\r
- Additional conversion parameters are specified in Flags. \r
+ Additional conversion parameters are specified in Flags.\r
The Flags bit LEFT_JUSTIFY is always ignored.\r
All conversions are left justified in Buffer.\r
If Width is 0, PREFIX_ZERO is ignored in Flags.\r
If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas\r
are inserted every 3rd digit starting from the right.\r
If Value is < 0, then the fist character in Buffer is a '-'.\r
- If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored, \r
- then Buffer is padded with '0' characters so the combination of the optional '-' \r
+ If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,\r
+ then Buffer is padded with '0' characters so the combination of the optional '-'\r
sign character, '0' characters, digit characters for Value, and the Null-terminator\r
add up to Width characters.\r
\r
@param Width The maximum number of characters to place in Buffer, not including\r
the Null-terminator.\r
@param Increment The character increment in Buffer.\r
- \r
+\r
@return Total number of characters required to perform the conversion.\r
\r
**/\r
ASSERT (((Flags & COMMA_TYPE) == 0) || ((Flags & RADIX_HEX) == 0));\r
\r
OriginalBuffer = Buffer;\r
- \r
+\r
//\r
// Width is 0 or COMMA_TYPE is set, PREFIX_ZERO is ignored.\r
//\r
if (Width == 0 || (Flags & COMMA_TYPE) != 0) {\r
- Flags &= (~PREFIX_ZERO);\r
+ Flags &= ~((UINTN) PREFIX_ZERO);\r
}\r
//\r
// If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.\r
// Set the tag for the end of the input Buffer.\r
//\r
EndBuffer = Buffer + Width * Increment;\r
- \r
+\r
//\r
// Convert decimal negative\r
//\r
Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, '-', Increment);\r
Width--;\r
}\r
- \r
+\r
//\r
// Count the length of the value string.\r
//\r
Radix = ((Flags & RADIX_HEX) == 0)? 10 : 16;\r
ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, Value, Radix);\r
Count = ValueBufferPtr - ValueBuffer;\r
- \r
+\r
//\r
// Append Zero\r
//\r
if ((Flags & PREFIX_ZERO) != 0) {\r
Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Count, '0', Increment);\r
}\r
- \r
+\r
//\r
// Print Comma type for every 3 characters\r
//\r
}\r
}\r
}\r
- \r
+\r
//\r
// Print Null-terminator\r
//\r
}\r
\r
/**\r
- Worker function that produces a Null-terminated string in an output buffer \r
+ Internal function that converts a decimal value to a Null-terminated string.\r
+\r
+ Converts the decimal number specified by Value to a Null-terminated string\r
+ specified by Buffer containing at most Width characters. If Width is 0 then a\r
+ width of MAXIMUM_VALUE_CHARACTERS is assumed. If the conversion contains more\r
+ than Width characters, then only the first Width characters are placed in\r
+ Buffer. Additional conversion parameters are specified in Flags.\r
+ The Flags bit LEFT_JUSTIFY is always ignored.\r
+ All conversions are left justified in Buffer.\r
+ If Width is 0, PREFIX_ZERO is ignored in Flags.\r
+ If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and\r
+ commas are inserted every 3rd digit starting from the right.\r
+ If Value is < 0, then the fist character in Buffer is a '-'.\r
+ If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,\r
+ then Buffer is padded with '0' characters so the combination of the optional\r
+ '-' sign character, '0' characters, digit characters for Value, and the\r
+ Null-terminator add up to Width characters.\r
+\r
+ If an error would be returned, the function will ASSERT().\r
+\r
+ @param Buffer The pointer to the output buffer for the produced\r
+ Null-terminated string.\r
+ @param BufferSize The size of Buffer in bytes, including the\r
+ Null-terminator.\r
+ @param Flags The bitmask of flags that specify left justification,\r
+ zero pad, and commas.\r
+ @param Value The 64-bit signed value to convert to a string.\r
+ @param Width The maximum number of characters to place in Buffer,\r
+ not including the Null-terminator.\r
+ @param Increment The character increment in Buffer.\r
+\r
+ @retval RETURN_SUCCESS The decimal value is converted.\r
+ @retval RETURN_BUFFER_TOO_SMALL If BufferSize cannot hold the converted\r
+ value.\r
+ @retval RETURN_INVALID_PARAMETER If Buffer is NULL.\r
+ If Increment is 1 and\r
+ PcdMaximumAsciiStringLength is not zero,\r
+ BufferSize is greater than\r
+ PcdMaximumAsciiStringLength.\r
+ If Increment is not 1 and\r
+ PcdMaximumUnicodeStringLength is not zero,\r
+ BufferSize is greater than\r
+ (PcdMaximumUnicodeStringLength *\r
+ sizeof (CHAR16) + 1).\r
+ If unsupported bits are set in Flags.\r
+ If both COMMA_TYPE and RADIX_HEX are set in\r
+ Flags.\r
+ If Width >= MAXIMUM_VALUE_CHARACTERS.\r
+\r
+**/\r
+RETURN_STATUS\r
+BasePrintLibConvertValueToStringS (\r
+ IN OUT CHAR8 *Buffer,\r
+ IN UINTN BufferSize,\r
+ IN UINTN Flags,\r
+ IN INT64 Value,\r
+ IN UINTN Width,\r
+ IN UINTN Increment\r
+ )\r
+{\r
+ CHAR8 *EndBuffer;\r
+ CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];\r
+ CHAR8 *ValueBufferPtr;\r
+ UINTN Count;\r
+ UINTN Digits;\r
+ UINTN Index;\r
+ UINTN Radix;\r
+\r
+ //\r
+ // 1. Buffer shall not be a null pointer.\r
+ //\r
+ SAFE_PRINT_CONSTRAINT_CHECK ((Buffer != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+ //\r
+ // 2. BufferSize shall not be greater than (RSIZE_MAX * sizeof (CHAR16)) for\r
+ // Unicode output string or shall not be greater than ASCII_RSIZE_MAX for\r
+ // Ascii output string.\r
+ //\r
+ if (Increment == 1) {\r
+ //\r
+ // Ascii output string\r
+ //\r
+ if (ASCII_RSIZE_MAX != 0) {\r
+ SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+ }\r
+ } else {\r
+ //\r
+ // Unicode output string\r
+ //\r
+ if (RSIZE_MAX != 0) {\r
+ SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize <= RSIZE_MAX * sizeof (CHAR16) + 1), RETURN_INVALID_PARAMETER);\r
+ }\r
+ }\r
+\r
+ //\r
+ // 3. Flags shall be set properly.\r
+ //\r
+ SAFE_PRINT_CONSTRAINT_CHECK (((Flags & ~(LEFT_JUSTIFY | COMMA_TYPE | PREFIX_ZERO | RADIX_HEX)) == 0), RETURN_INVALID_PARAMETER);\r
+ SAFE_PRINT_CONSTRAINT_CHECK ((((Flags & COMMA_TYPE) == 0) || ((Flags & RADIX_HEX) == 0)), RETURN_INVALID_PARAMETER);\r
+\r
+ //\r
+ // 4. Width shall be smaller than MAXIMUM_VALUE_CHARACTERS.\r
+ //\r
+ SAFE_PRINT_CONSTRAINT_CHECK ((Width < MAXIMUM_VALUE_CHARACTERS), RETURN_INVALID_PARAMETER);\r
+\r
+ //\r
+ // Width is 0 or COMMA_TYPE is set, PREFIX_ZERO is ignored.\r
+ //\r
+ if (Width == 0 || (Flags & COMMA_TYPE) != 0) {\r
+ Flags &= ~((UINTN) PREFIX_ZERO);\r
+ }\r
+ //\r
+ // If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.\r
+ //\r
+ if (Width == 0) {\r
+ Width = MAXIMUM_VALUE_CHARACTERS - 1;\r
+ }\r
+\r
+ //\r
+ // Count the characters of the output string.\r
+ //\r
+ Count = 0;\r
+ Radix = ((Flags & RADIX_HEX) == 0)? 10 : 16;\r
+\r
+ if ((Flags & PREFIX_ZERO) != 0) {\r
+ Count = Width;\r
+ } else {\r
+ if ((Value < 0) && ((Flags & RADIX_HEX) == 0)) {\r
+ Count++; // minus sign\r
+ ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, -Value, Radix);\r
+ } else {\r
+ ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, Value, Radix);\r
+ }\r
+ Digits = ValueBufferPtr - ValueBuffer;\r
+ Count += Digits;\r
+\r
+ if ((Flags & COMMA_TYPE) != 0) {\r
+ Count += (Digits - 1) / 3; // commas\r
+ }\r
+ }\r
+\r
+ Width = MIN (Count, Width);\r
+\r
+ //\r
+ // 5. BufferSize shall be large enough to hold the converted string.\r
+ //\r
+ SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize >= (Width + 1) * Increment), RETURN_BUFFER_TOO_SMALL);\r
+\r
+ //\r
+ // Set the tag for the end of the input Buffer.\r
+ //\r
+ EndBuffer = Buffer + Width * Increment;\r
+\r
+ //\r
+ // Convert decimal negative\r
+ //\r
+ if ((Value < 0) && ((Flags & RADIX_HEX) == 0)) {\r
+ Value = -Value;\r
+ Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, '-', Increment);\r
+ Width--;\r
+ }\r
+\r
+ //\r
+ // Count the length of the value string.\r
+ //\r
+ ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, Value, Radix);\r
+ Count = ValueBufferPtr - ValueBuffer;\r
+\r
+ //\r
+ // Append Zero\r
+ //\r
+ if ((Flags & PREFIX_ZERO) != 0) {\r
+ Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Count, '0', Increment);\r
+ }\r
+\r
+ //\r
+ // Print Comma type for every 3 characters\r
+ //\r
+ Digits = Count % 3;\r
+ if (Digits != 0) {\r
+ Digits = 3 - Digits;\r
+ }\r
+ for (Index = 0; Index < Count; Index++) {\r
+ Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, *ValueBufferPtr--, Increment);\r
+ if ((Flags & COMMA_TYPE) != 0) {\r
+ Digits++;\r
+ if (Digits == 3) {\r
+ Digits = 0;\r
+ if ((Index + 1) < Count) {\r
+ Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', Increment);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Print Null-terminator\r
+ //\r
+ BasePrintLibFillBuffer (Buffer, EndBuffer + Increment, 1, 0, Increment);\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ Worker function that produces a Null-terminated string in an output buffer\r
based on a Null-terminated format string and a VA_LIST argument list.\r
\r
- VSPrint function to process format and place the results in Buffer. Since a \r
- VA_LIST is used this routine allows the nesting of Vararg routines. Thus \r
+ VSPrint function to process format and place the results in Buffer. Since a\r
+ VA_LIST is used this routine allows the nesting of Vararg routines. Thus\r
this is the main print working routine.\r
\r
If COUNT_ONLY_NO_PRINT is set in Flags, Buffer will not be modified at all.\r
\r
- @param[out] Buffer The character buffer to print the results of the \r
+ @param[out] Buffer The character buffer to print the results of the\r
parsing of Format into.\r
- @param[in] BufferSize The maximum number of characters to put into \r
+ @param[in] BufferSize The maximum number of characters to put into\r
buffer.\r
@param[in] Flags Initial flags value.\r
- Can only have FORMAT_UNICODE, OUTPUT_UNICODE, \r
+ Can only have FORMAT_UNICODE, OUTPUT_UNICODE,\r
and COUNT_ONLY_NO_PRINT set.\r
@param[in] Format A Null-terminated format string.\r
@param[in] VaListMarker VA_LIST style variable argument list consumed by\r
\r
//\r
// If you change this code be sure to match the 2 versions of this function.\r
- // Nearly identical logic is found in the BasePrintLib and \r
+ // Nearly identical logic is found in the BasePrintLib and\r
// DxePrintLibPrint2Protocol (both PrintLib instances).\r
//\r
\r
+ //\r
+ // 1. Buffer shall not be a null pointer when both BufferSize > 0 and\r
+ // COUNT_ONLY_NO_PRINT is not set in Flags.\r
+ //\r
+ if ((BufferSize > 0) && ((Flags & COUNT_ONLY_NO_PRINT) == 0)) {\r
+ SAFE_PRINT_CONSTRAINT_CHECK ((Buffer != NULL), 0);\r
+ }\r
+\r
+ //\r
+ // 2. Format shall not be a null pointer when BufferSize > 0 or when\r
+ // COUNT_ONLY_NO_PRINT is set in Flags.\r
+ //\r
+ if ((BufferSize > 0) || ((Flags & COUNT_ONLY_NO_PRINT) != 0)) {\r
+ SAFE_PRINT_CONSTRAINT_CHECK ((Format != NULL), 0);\r
+ }\r
+\r
+ //\r
+ // 3. BufferSize shall not be greater than RSIZE_MAX for Unicode output or\r
+ // ASCII_RSIZE_MAX for Ascii output.\r
+ //\r
+ if ((Flags & OUTPUT_UNICODE) != 0) {\r
+ if (RSIZE_MAX != 0) {\r
+ SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize <= RSIZE_MAX), 0);\r
+ }\r
+ BytesPerOutputCharacter = 2;\r
+ } else {\r
+ if (ASCII_RSIZE_MAX != 0) {\r
+ SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize <= ASCII_RSIZE_MAX), 0);\r
+ }\r
+ BytesPerOutputCharacter = 1;\r
+ }\r
+\r
+ //\r
+ // 4. Format shall not contain more than RSIZE_MAX Unicode characters or\r
+ // ASCII_RSIZE_MAX Ascii characters.\r
+ //\r
+ if ((Flags & FORMAT_UNICODE) != 0) {\r
+ if (RSIZE_MAX != 0) {\r
+ SAFE_PRINT_CONSTRAINT_CHECK ((StrnLenS ((CHAR16 *)Format, RSIZE_MAX + 1) <= RSIZE_MAX), 0);\r
+ }\r
+ BytesPerFormatCharacter = 2;\r
+ FormatMask = 0xffff;\r
+ } else {\r
+ if (ASCII_RSIZE_MAX != 0) {\r
+ SAFE_PRINT_CONSTRAINT_CHECK ((AsciiStrnLenS (Format, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), 0);\r
+ }\r
+ BytesPerFormatCharacter = 1;\r
+ FormatMask = 0xff;\r
+ }\r
+\r
if ((Flags & COUNT_ONLY_NO_PRINT) != 0) {\r
if (BufferSize == 0) {\r
Buffer = NULL;\r
if (BufferSize == 0) {\r
return 0;\r
}\r
- ASSERT (Buffer != NULL);\r
- }\r
-\r
- if ((Flags & OUTPUT_UNICODE) != 0) {\r
- BytesPerOutputCharacter = 2;\r
- } else {\r
- BytesPerOutputCharacter = 1;\r
}\r
\r
LengthToReturn = 0;\r
+ EndBuffer = NULL;\r
+ OriginalBuffer = NULL;\r
\r
//\r
// Reserve space for the Null terminator.\r
//\r
- BufferSize--;\r
- OriginalBuffer = Buffer;\r
+ if (Buffer != NULL) {\r
+ BufferSize--;\r
+ OriginalBuffer = Buffer;\r
\r
- //\r
- // Set the tag for the end of the input Buffer.\r
- //\r
- EndBuffer = Buffer + BufferSize * BytesPerOutputCharacter;\r
-\r
- if ((Flags & FORMAT_UNICODE) != 0) {\r
//\r
- // Make sure format string cannot contain more than PcdMaximumUnicodeStringLength\r
- // Unicode characters if PcdMaximumUnicodeStringLength is not zero. \r
+ // Set the tag for the end of the input Buffer.\r
//\r
- ASSERT (StrSize ((CHAR16 *) Format) != 0);\r
- BytesPerFormatCharacter = 2;\r
- FormatMask = 0xffff;\r
- } else {\r
- //\r
- // Make sure format string cannot contain more than PcdMaximumAsciiStringLength\r
- // Ascii characters if PcdMaximumAsciiStringLength is not zero. \r
- //\r
- ASSERT (AsciiStrSize (Format) != 0);\r
- BytesPerFormatCharacter = 1;\r
- FormatMask = 0xff;\r
+ EndBuffer = Buffer + BufferSize * BytesPerOutputCharacter;\r
}\r
\r
//\r
// Get the first character from the format string\r
//\r
- FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
+ FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
\r
//\r
// Loop until the end of the format string is reached or the output buffer is full\r
//\r
- while (FormatCharacter != 0 && Buffer < EndBuffer) {\r
+ while (FormatCharacter != 0) {\r
+ if ((Buffer != NULL) && (Buffer >= EndBuffer)) {\r
+ break;\r
+ }\r
//\r
// Clear all the flag bits except those that may have been passed in\r
//\r
- Flags &= (OUTPUT_UNICODE | FORMAT_UNICODE | COUNT_ONLY_NO_PRINT);\r
+ Flags &= (UINTN) (OUTPUT_UNICODE | FORMAT_UNICODE | COUNT_ONLY_NO_PRINT);\r
\r
//\r
// Set the default width to zero, and the default precision to 1\r
//\r
for (Done = FALSE; !Done; ) {\r
Format += BytesPerFormatCharacter;\r
- FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
+ FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
switch (FormatCharacter) {\r
- case '.': \r
- Flags |= PRECISION; \r
+ case '.':\r
+ Flags |= PRECISION;\r
break;\r
- case '-': \r
- Flags |= LEFT_JUSTIFY; \r
+ case '-':\r
+ Flags |= LEFT_JUSTIFY;\r
break;\r
- case '+': \r
- Flags |= PREFIX_SIGN; \r
+ case '+':\r
+ Flags |= PREFIX_SIGN;\r
break;\r
- case ' ': \r
- Flags |= PREFIX_BLANK; \r
+ case ' ':\r
+ Flags |= PREFIX_BLANK;\r
break;\r
- case ',': \r
- Flags |= COMMA_TYPE; \r
+ case ',':\r
+ Flags |= COMMA_TYPE;\r
break;\r
case 'L':\r
- case 'l': \r
- Flags |= LONG_TYPE; \r
+ case 'l':\r
+ Flags |= LONG_TYPE;\r
break;\r
case '*':\r
if ((Flags & PRECISION) == 0) {\r
for (Count = 0; ((FormatCharacter >= '0') && (FormatCharacter <= '9')); ){\r
Count = (Count * 10) + FormatCharacter - '0';\r
Format += BytesPerFormatCharacter;\r
- FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
+ FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
}\r
Format -= BytesPerFormatCharacter;\r
if ((Flags & PRECISION) == 0) {\r
Precision = Count;\r
}\r
break;\r
- \r
+\r
case '\0':\r
//\r
// Make no output if Format string terminates unexpectedly when\r
- // looking up for flag, width, precision and type. \r
+ // looking up for flag, width, precision and type.\r
//\r
Format -= BytesPerFormatCharacter;\r
Precision = 0;\r
Done = TRUE;\r
break;\r
}\r
- } \r
+ }\r
\r
//\r
// Handle each argument type\r
//\r
// Flag space, +, 0, L & l are invalid for type p.\r
//\r
- Flags &= ~(PREFIX_BLANK | PREFIX_SIGN | PREFIX_ZERO | LONG_TYPE);\r
+ Flags &= ~((UINTN) (PREFIX_BLANK | PREFIX_SIGN | PREFIX_ZERO | LONG_TYPE));\r
if (sizeof (VOID *) > 4) {\r
Flags |= LONG_TYPE;\r
}\r
+ //\r
+ // break skipped on purpose\r
+ //\r
case 'X':\r
Flags |= PREFIX_ZERO;\r
//\r
//\r
// break skipped on purpose\r
//\r
+ case 'u':\r
+ if ((Flags & RADIX_HEX) == 0) {\r
+ Flags &= ~((UINTN) (PREFIX_SIGN));\r
+ Flags |= UNSIGNED_TYPE;\r
+ }\r
+ //\r
+ // break skipped on purpose\r
+ //\r
case 'd':\r
if ((Flags & LONG_TYPE) == 0) {\r
//\r
- // 'd','x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".\r
+ // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".\r
// This assumption is made so the format string definition is compatible with the ANSI C\r
- // Specification for formatted strings. It is recommended that the Base Types be used \r
- // everywhere, but in this one case, compliance with ANSI C is more important, and \r
- // provides an implementation that is compatible with that largest possible set of CPU \r
+ // Specification for formatted strings. It is recommended that the Base Types be used\r
+ // everywhere, but in this one case, compliance with ANSI C is more important, and\r
+ // provides an implementation that is compatible with that largest possible set of CPU\r
// architectures. This is why the type "int" is used in this one case.\r
//\r
if (BaseListMarker == NULL) {\r
if ((Flags & RADIX_HEX) == 0) {\r
Radix = 10;\r
if (Comma) {\r
- Flags &= (~PREFIX_ZERO);\r
+ Flags &= ~((UINTN) PREFIX_ZERO);\r
Precision = 1;\r
}\r
- if (Value < 0) {\r
+ if (Value < 0 && (Flags & UNSIGNED_TYPE) == 0) {\r
Flags |= PREFIX_SIGN;\r
Prefix = '-';\r
Value = -Value;\r
+ } else if ((Flags & UNSIGNED_TYPE) != 0 && (Flags & LONG_TYPE) == 0) {\r
+ //\r
+ // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".\r
+ // This assumption is made so the format string definition is compatible with the ANSI C\r
+ // Specification for formatted strings. It is recommended that the Base Types be used\r
+ // everywhere, but in this one case, compliance with ANSI C is more important, and\r
+ // provides an implementation that is compatible with that largest possible set of CPU\r
+ // architectures. This is why the type "unsigned int" is used in this one case.\r
+ //\r
+ Value = (unsigned int)Value;\r
}\r
} else {\r
Radix = 16;\r
Comma = FALSE;\r
if ((Flags & LONG_TYPE) == 0 && Value < 0) {\r
//\r
- // 'd','x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".\r
+ // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".\r
// This assumption is made so the format string definition is compatible with the ANSI C\r
- // Specification for formatted strings. It is recommended that the Base Types be used \r
- // everywhere, but in this one case, compliance with ANSI C is more important, and \r
- // provides an implementation that is compatible with that largest possible set of CPU \r
+ // Specification for formatted strings. It is recommended that the Base Types be used\r
+ // everywhere, but in this one case, compliance with ANSI C is more important, and\r
+ // provides an implementation that is compatible with that largest possible set of CPU\r
// architectures. This is why the type "unsigned int" is used in this one case.\r
//\r
Value = (unsigned int)Value;\r
Count = 0;\r
}\r
ArgumentString = (CHAR8 *)ValueBuffer + Count;\r
- \r
+\r
Digits = Count % 3;\r
if (Digits != 0) {\r
Digits = 3 - Digits;\r
ArgumentString = BASE_ARG (BaseListMarker, CHAR8 *);\r
}\r
if (ArgumentString == NULL) {\r
- Flags &= (~ARGUMENT_UNICODE);\r
+ Flags &= ~((UINTN) ARGUMENT_UNICODE);\r
ArgumentString = "<null string>";\r
}\r
//\r
GuidData3 = ReadUnaligned16 (&(TmpGuid->Data3));\r
BasePrintLibSPrint (\r
ValueBuffer,\r
- MAXIMUM_VALUE_CHARACTERS, \r
+ MAXIMUM_VALUE_CHARACTERS,\r
0,\r
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",\r
GuidData1,\r
\r
case 't':\r
if (BaseListMarker == NULL) {\r
- TmpTime = VA_ARG (VaListMarker, TIME *); \r
+ TmpTime = VA_ARG (VaListMarker, TIME *);\r
} else {\r
- TmpTime = BASE_ARG (BaseListMarker, TIME *); \r
+ TmpTime = BASE_ARG (BaseListMarker, TIME *);\r
}\r
if (TmpTime == NULL) {\r
ArgumentString = "<null time>";\r
\r
case '\r':\r
Format += BytesPerFormatCharacter;\r
- FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
+ FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
if (FormatCharacter == '\n') {\r
//\r
// Translate '\r\n' to '\r\n'\r
//\r
ArgumentString = "\r\n";\r
Format += BytesPerFormatCharacter;\r
- FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
+ FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
if (FormatCharacter != '\r') {\r
Format -= BytesPerFormatCharacter;\r
}\r
break;\r
}\r
break;\r
- \r
+\r
case '\r':\r
Format += BytesPerFormatCharacter;\r
- FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
+ FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
if (FormatCharacter == '\n') {\r
//\r
// Translate '\r\n' to '\r\n'\r
//\r
ArgumentString = "\r\n";\r
Format += BytesPerFormatCharacter;\r
- FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
+ FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
if (FormatCharacter != '\r') {\r
Format -= BytesPerFormatCharacter;\r
}\r
// Compute the number of characters in ArgumentString and store it in Count\r
// ArgumentString is either null-terminated, or it contains Precision characters\r
//\r
- for (Count = 0; Count < Precision || ((Flags & PRECISION) == 0); Count++) {\r
+ for (Count = 0;\r
+ (ArgumentString[Count * BytesPerArgumentCharacter] != '\0' ||\r
+ (BytesPerArgumentCharacter > 1 &&\r
+ ArgumentString[Count * BytesPerArgumentCharacter + 1]!= '\0')) &&\r
+ (Count < Precision || ((Flags & PRECISION) == 0));\r
+ Count++) {\r
ArgumentCharacter = ((ArgumentString[Count * BytesPerArgumentCharacter] & 0xff) | ((ArgumentString[Count * BytesPerArgumentCharacter + 1]) << 8)) & ArgumentMask;\r
if (ArgumentCharacter == 0) {\r
break;\r
//\r
// Copy the string into the output buffer performing the required type conversions\r
//\r
- while (Index < Count) {\r
- ArgumentCharacter = ((*ArgumentString & 0xff) | (*(ArgumentString + 1) << 8)) & ArgumentMask;\r
+ while (Index < Count &&\r
+ (ArgumentString[0] != '\0' ||\r
+ (BytesPerArgumentCharacter > 1 && ArgumentString[1] != '\0'))) {\r
+ ArgumentCharacter = ((*ArgumentString & 0xff) | (((UINT8)*(ArgumentString + 1)) << 8)) & ArgumentMask;\r
\r
LengthToReturn += (1 * BytesPerOutputCharacter);\r
if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {\r
//\r
// Get the next character from the format string\r
//\r
- FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
+ FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
}\r
\r
- if (Flags & COUNT_ONLY_NO_PRINT) {\r
+ if ((Flags & COUNT_ONLY_NO_PRINT) != 0) {\r
return (LengthToReturn / BytesPerOutputCharacter);\r
}\r
\r
// Null terminate the Unicode or ASCII string\r
//\r
BasePrintLibFillBuffer (Buffer, EndBuffer + BytesPerOutputCharacter, 1, 0, BytesPerOutputCharacter);\r
- //\r
- // Make sure output buffer cannot contain more than PcdMaximumUnicodeStringLength\r
- // Unicode characters if PcdMaximumUnicodeStringLength is not zero. \r
- //\r
- ASSERT ((((Flags & OUTPUT_UNICODE) == 0)) || (StrSize ((CHAR16 *) OriginalBuffer) != 0));\r
- //\r
- // Make sure output buffer cannot contain more than PcdMaximumAsciiStringLength\r
- // ASCII characters if PcdMaximumAsciiStringLength is not zero. \r
- //\r
- ASSERT ((((Flags & OUTPUT_UNICODE) != 0)) || (AsciiStrSize (OriginalBuffer) != 0));\r
\r
return ((Buffer - OriginalBuffer) / BytesPerOutputCharacter);\r
}\r
\r
/**\r
- Worker function that produces a Null-terminated string in an output buffer \r
+ Worker function that produces a Null-terminated string in an output buffer\r
based on a Null-terminated format string and variable argument list.\r
\r
- VSPrint function to process format and place the results in Buffer. Since a \r
- VA_LIST is used this routine allows the nesting of Vararg routines. Thus \r
+ VSPrint function to process format and place the results in Buffer. Since a\r
+ VA_LIST is used this routine allows the nesting of Vararg routines. Thus\r
this is the main print working routine\r
\r
@param StartOfBuffer The character buffer to print the results of the parsing\r
)\r
{\r
VA_LIST Marker;\r
+ UINTN NumberOfPrinted;\r
\r
VA_START (Marker, FormatString);\r
- return BasePrintLibSPrintMarker (StartOfBuffer, BufferSize, Flags, FormatString, Marker, NULL);\r
+ NumberOfPrinted = BasePrintLibSPrintMarker (StartOfBuffer, BufferSize, Flags, FormatString, Marker, NULL);\r
+ VA_END (Marker);\r
+ return NumberOfPrinted;\r
}\r