2 Print Library internal worker functions.
4 Copyright (c) 2006 - 2008, Intel Corporation<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "PrintLibInternal.h"
17 #define WARNING_STATUS_NUMBER 4
18 #define ERROR_STATUS_NUMBER 24
20 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexStr
[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
22 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mStatusString
[] = {
23 "Success", // RETURN_SUCCESS = 0
24 "Warning Unknown Glyph", // RETURN_WARN_UNKNOWN_GLYPH = 1
25 "Warning Delete Failure", // RETURN_WARN_DELETE_FAILURE = 2
26 "Warning Write Failure", // RETURN_WARN_WRITE_FAILURE = 3
27 "Warning Buffer Too Small", // RETURN_WARN_BUFFER_TOO_SMALL = 4
28 "Load Error", // RETURN_LOAD_ERROR = 1 | MAX_BIT
29 "Invalid Parameter", // RETURN_INVALID_PARAMETER = 2 | MAX_BIT
30 "Unsupported", // RETURN_UNSUPPORTED = 3 | MAX_BIT
31 "Bad Buffer Size", // RETURN_BAD_BUFFER_SIZE = 4 | MAX_BIT
32 "Buffer Too Small", // RETURN_BUFFER_TOO_SMALL, = 5 | MAX_BIT
33 "Not Ready", // RETURN_NOT_READY = 6 | MAX_BIT
34 "Device Error", // RETURN_DEVICE_ERROR = 7 | MAX_BIT
35 "Write Protected", // RETURN_WRITE_PROTECTED = 8 | MAX_BIT
36 "Out of Resources", // RETURN_OUT_OF_RESOURCES = 9 | MAX_BIT
37 "Volume Corrupt", // RETURN_VOLUME_CORRUPTED = 10 | MAX_BIT
38 "Volume Full", // RETURN_VOLUME_FULL = 11 | MAX_BIT
39 "No Media", // RETURN_NO_MEDIA = 12 | MAX_BIT
40 "Media changed", // RETURN_MEDIA_CHANGED = 13 | MAX_BIT
41 "Not Found", // RETURN_NOT_FOUND = 14 | MAX_BIT
42 "Access Denied", // RETURN_ACCESS_DENIED = 15 | MAX_BIT
43 "No Response", // RETURN_NO_RESPONSE = 16 | MAX_BIT
44 "No mapping", // RETURN_NO_MAPPING = 17 | MAX_BIT
45 "Time out", // RETURN_TIMEOUT = 18 | MAX_BIT
46 "Not started", // RETURN_NOT_STARTED = 19 | MAX_BIT
47 "Already started", // RETURN_ALREADY_STARTED = 20 | MAX_BIT
48 "Aborted", // RETURN_ABORTED = 21 | MAX_BIT
49 "ICMP Error", // RETURN_ICMP_ERROR = 22 | MAX_BIT
50 "TFTP Error", // RETURN_TFTP_ERROR = 23 | MAX_BIT
51 "Protocol Error" // RETURN_PROTOCOL_ERROR = 24 | MAX_BIT
56 Internal function that places the character into the Buffer.
58 Internal function that places ASCII or Unicode character into the Buffer.
60 @param Buffer Buffer to place the Unicode or ASCII string.
61 @param EndBuffer The end of the input Buffer. No characters will be
63 @param Length Count of character to be placed into Buffer.
64 @param Character Character to be placed into Buffer.
65 @param Increment Character increment in Buffer.
67 @return Buffer Buffer filled with the input Character.
71 BasePrintLibFillBuffer (
81 for (Index
= 0; Index
< Length
&& Buffer
< EndBuffer
; Index
++) {
82 *Buffer
= (CHAR8
) Character
;
83 *(Buffer
+ 1) = (CHAR8
) (Character
>> 8);
87 for (Index
= 0; Index
< Length
&& Buffer
< EndBuffer
; Index
++) {
88 *Buffer
= (CHAR8
) Character
;
96 Internal function that convert a decimal number to a string in Buffer.
98 Print worker function that convert a decimal number to a string in Buffer.
100 @param Buffer Location to place the Unicode or ASCII string of Value.
101 @param Value Value to convert to a Decimal or Hexidecimal string in Buffer.
102 @param Radix Radix of the value
104 @return Number of characters printed.
108 BasePrintLibValueToString (
109 IN OUT CHAR8
*Buffer
,
118 // Loop to convert one digit at a time in reverse order
123 Value
= (INT64
)DivU64x32Remainder ((UINT64
)Value
, (UINT32
)Radix
, &Remainder
);
124 *(Buffer
++) = mHexStr
[Remainder
];
126 } while (Value
!= 0);
129 // the length of Buffer string converted from Value
135 Internal function that converts a decimal value to a Null-terminated string.
137 Converts the decimal number specified by Value to a Null-terminated
138 string specified by Buffer containing at most Width characters.
139 If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
140 The total number of characters placed in Buffer is returned.
141 If the conversion contains more than Width characters, then only the first
142 Width characters are returned, and the total number of characters
143 required to perform the conversion is returned.
144 Additional conversion parameters are specified in Flags.
145 The Flags bit LEFT_JUSTIFY is always ignored.
146 All conversions are left justified in Buffer.
147 If Width is 0, PREFIX_ZERO is ignored in Flags.
148 If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas
149 are inserted every 3rd digit starting from the right.
150 If Value is < 0, then the fist character in Buffer is a '-'.
151 If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,
152 then Buffer is padded with '0' characters so the combination of the optional '-'
153 sign character, '0' characters, digit characters for Value, and the Null-terminator
154 add up to Width characters.
156 If Buffer is NULL, then ASSERT().
157 If unsupported bits are set in Flags, then ASSERT().
158 If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()
160 @param Buffer Pointer to the output buffer for the produced Null-terminated
162 @param Flags The bitmask of flags that specify left justification, zero pad,
164 @param Value The 64-bit signed value to convert to a string.
165 @param Width The maximum number of characters to place in Buffer, not including
167 @param Increment Character increment in Buffer.
169 @return Total number of characters required to perform the conversion.
173 BasePrintLibConvertValueToString (
174 IN OUT CHAR8
*Buffer
,
181 CHAR8
*OriginalBuffer
;
183 CHAR8 ValueBuffer
[MAXIMUM_VALUE_CHARACTERS
];
190 // Make sure Buffer is not NULL and Width < MAXIMUM
192 ASSERT (Buffer
!= NULL
);
193 ASSERT (Width
< MAXIMUM_VALUE_CHARACTERS
);
195 // Make sure Flags can only contain supported bits.
197 ASSERT ((Flags
& ~(LEFT_JUSTIFY
| COMMA_TYPE
| PREFIX_ZERO
| RADIX_HEX
)) == 0);
200 // If both COMMA_TYPE and HEX_RADIX are set, then ASSERT ()
202 ASSERT (((Flags
& COMMA_TYPE
) != 0 && (Flags
& RADIX_HEX
) != 0) == FALSE
);
204 OriginalBuffer
= Buffer
;
207 // Width is 0 or COMMA_TYPE is set, PREFIX_ZERO is ignored.
209 if (Width
== 0 || (Flags
& COMMA_TYPE
) != 0) {
210 Flags
&= (~PREFIX_ZERO
);
213 // If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
216 Width
= MAXIMUM_VALUE_CHARACTERS
- 1;
219 // Set the tag for the end of the input Buffer.
221 EndBuffer
= Buffer
+ Width
* Increment
;
224 // Convert decimal negative
226 if ((Value
< 0) && ((Flags
& RADIX_HEX
) == 0)) {
228 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, '-', Increment
);
233 // Count the length of the value string.
235 Radix
= ((Flags
& RADIX_HEX
) == 0)? 10 : 16;
236 Count
= BasePrintLibValueToString (ValueBuffer
, Value
, Radix
);
241 if ((Flags
& PREFIX_ZERO
) != 0) {
242 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, Width
- Count
, '0', Increment
);
246 // Print Comma type for every 3 characters
252 for (Index
= 0; Index
< Count
; Index
++) {
253 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, ValueBuffer
[Count
- Index
], Increment
);
254 if ((Flags
& COMMA_TYPE
) != 0) {
258 if ((Index
+ 1) < Count
) {
259 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, ',', Increment
);
266 // Print Null-terminator
268 BasePrintLibFillBuffer (Buffer
, EndBuffer
+ Increment
, 1, 0, Increment
);
270 return ((Buffer
- OriginalBuffer
) / Increment
);
274 Worker function that produces a Null-terminated string in an output buffer
275 based on a Null-terminated format string and a VA_LIST argument list.
277 VSPrint function to process format and place the results in Buffer. Since a
278 VA_LIST is used this rountine allows the nesting of Vararg routines. Thus
279 this is the main print working routine.
281 @param Buffer Character buffer to print the results of the parsing
283 @param BufferSize Maximum number of characters to put into buffer.
284 @param Flags Intial flags value.
285 Can only have FORMAT_UNICODE and OUTPUT_UNICODE set.
286 @param Format Null-terminated format string.
287 @param Marker Vararg list consumed by processing Format.
289 @return Number of characters printed not including the Null-terminator.
293 BasePrintLibVSPrint (
297 IN CONST CHAR8
*Format
,
301 CHAR8
*OriginalBuffer
;
303 CHAR8 ValueBuffer
[MAXIMUM_VALUE_CHARACTERS
];
304 UINTN BytesPerOutputCharacter
;
305 UINTN BytesPerFormatCharacter
;
307 UINTN FormatCharacter
;
311 CONST CHAR8
*ArgumentString
;
317 INTN BytesPerArgumentCharacter
;
318 UINTN ArgumentCharacter
;
326 RETURN_STATUS Status
;
328 if (BufferSize
== 0) {
331 ASSERT (Buffer
!= NULL
);
333 if ((Flags
& OUTPUT_UNICODE
) != 0) {
334 BytesPerOutputCharacter
= 2;
336 BytesPerOutputCharacter
= 1;
340 // Reserve space for the Null terminator.
343 OriginalBuffer
= Buffer
;
345 // Set the tag for the end of the input Buffer.
347 EndBuffer
= Buffer
+ BufferSize
* BytesPerOutputCharacter
;
349 if ((Flags
& FORMAT_UNICODE
) != 0) {
351 // Make sure format string cannot contain more than PcdMaximumUnicodeStringLength
352 // Unicode characters if PcdMaximumUnicodeStringLength is not zero.
354 ASSERT (StrSize ((CHAR16
*) Format
) != 0);
355 BytesPerFormatCharacter
= 2;
359 // Make sure format string cannot contain more than PcdMaximumAsciiStringLength
360 // Ascii characters if PcdMaximumAsciiStringLength is not zero.
362 ASSERT (AsciiStrSize (Format
) != 0);
363 BytesPerFormatCharacter
= 1;
370 // Get the first character from the format string
372 FormatCharacter
= ((*Format
& 0xff) | (*(Format
+ 1) << 8)) & FormatMask
;
375 // Loop until the end of the format string is reached or the output buffer is full
377 while (FormatCharacter
!= 0 && Buffer
< EndBuffer
) {
379 // Clear all the flag bits except those that may have been passed in
381 Flags
&= (OUTPUT_UNICODE
| FORMAT_UNICODE
);
384 // Set the default width to zero, and the default precision to 1
394 switch (FormatCharacter
) {
397 // Parse Flags and Width
399 for (Done
= FALSE
; !Done
; ) {
400 Format
+= BytesPerFormatCharacter
;
401 FormatCharacter
= ((*Format
& 0xff) | (*(Format
+ 1) << 8)) & FormatMask
;
402 switch (FormatCharacter
) {
407 Flags
|= LEFT_JUSTIFY
;
410 Flags
|= PREFIX_SIGN
;
413 Flags
|= PREFIX_BLANK
;
423 if ((Flags
& PRECISION
) == 0) {
424 Flags
|= PAD_TO_WIDTH
;
425 Width
= VA_ARG (Marker
, UINTN
);
427 Precision
= VA_ARG (Marker
, UINTN
);
431 if ((Flags
& PRECISION
) == 0) {
432 Flags
|= PREFIX_ZERO
;
443 for (Count
= 0; ((FormatCharacter
>= '0') && (FormatCharacter
<= '9')); ){
444 Count
= (Count
* 10) + FormatCharacter
- '0';
445 Format
+= BytesPerFormatCharacter
;
446 FormatCharacter
= ((*Format
& 0xff) | (*(Format
+ 1) << 8)) & FormatMask
;
448 Format
-= BytesPerFormatCharacter
;
449 if ((Flags
& PRECISION
) == 0) {
450 Flags
|= PAD_TO_WIDTH
;
459 // Make no output if Format string terminates unexpectedly when
460 // looking up for flag, width, precision and type.
462 Format
-= BytesPerFormatCharacter
;
465 // break skipped on purpose.
474 // Handle each argument type
476 switch (FormatCharacter
) {
479 // Flag space, +, 0, L & l are invalid for type p.
481 Flags
&= ~(PREFIX_BLANK
| PREFIX_SIGN
| PREFIX_ZERO
| LONG_TYPE
);
482 if (sizeof (VOID
*) > 4) {
486 Flags
|= PREFIX_ZERO
;
488 // break skipped on purpose
493 // break skipped on purpose
496 if ((Flags
& LONG_TYPE
) == 0) {
497 Value
= (VA_ARG (Marker
, int));
499 Value
= VA_ARG (Marker
, INT64
);
501 if ((Flags
& PREFIX_BLANK
) != 0) {
504 if ((Flags
& PREFIX_SIGN
) != 0) {
507 if ((Flags
& COMMA_TYPE
) != 0) {
510 if ((Flags
& RADIX_HEX
) == 0) {
513 Flags
&= (~PREFIX_ZERO
);
517 Flags
|= PREFIX_SIGN
;
524 if ((Flags
& LONG_TYPE
) == 0 && Value
< 0) {
525 Value
= (unsigned int)Value
;
529 // Convert Value to a reversed string
531 Count
= BasePrintLibValueToString (ValueBuffer
, Value
, Radix
);
532 if (Value
== 0 && Precision
== 0) {
535 ArgumentString
= (CHAR8
*)ValueBuffer
+ Count
;
541 if (Comma
&& Count
!= 0) {
542 Count
+= ((Count
- 1) / 3);
548 Flags
|= ARGUMENT_REVERSED
;
550 if ((Flags
& PREFIX_ZERO
) != 0) {
551 if ((Flags
& LEFT_JUSTIFY
) == 0) {
552 if ((Flags
& PAD_TO_WIDTH
) != 0) {
553 if ((Flags
& PRECISION
) == 0) {
563 Flags
|= ARGUMENT_UNICODE
;
565 // break skipped on purpose
568 ArgumentString
= (CHAR8
*)VA_ARG (Marker
, CHAR8
*);
569 if (ArgumentString
== NULL
) {
570 Flags
&= (~ARGUMENT_UNICODE
);
571 ArgumentString
= "<null string>";
574 // Set the default precision for string to be zero if not specified.
576 if ((Flags
& PRECISION
) == 0) {
582 Character
= VA_ARG (Marker
, UINTN
) & 0xffff;
583 ArgumentString
= (CHAR8
*)&Character
;
584 Flags
|= ARGUMENT_UNICODE
;
588 TmpGuid
= VA_ARG (Marker
, GUID
*);
589 if (TmpGuid
== NULL
) {
590 ArgumentString
= "<null guid>";
594 MAXIMUM_VALUE_CHARACTERS
,
596 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
609 ArgumentString
= ValueBuffer
;
614 TmpTime
= VA_ARG (Marker
, TIME
*);
615 if (TmpTime
== NULL
) {
616 ArgumentString
= "<null time>";
620 MAXIMUM_VALUE_CHARACTERS
,
622 "%02d/%02d/%04d %02d:%02d",
629 ArgumentString
= ValueBuffer
;
634 Status
= VA_ARG (Marker
, RETURN_STATUS
);
635 ArgumentString
= ValueBuffer
;
636 if (RETURN_ERROR (Status
)) {
640 Index
= Status
& ~MAX_BIT
;
641 if (Index
> 0 && Index
<= ERROR_STATUS_NUMBER
) {
642 ArgumentString
= mStatusString
[Index
+ WARNING_STATUS_NUMBER
];
646 if (Index
<= WARNING_STATUS_NUMBER
) {
647 ArgumentString
= mStatusString
[Index
];
650 if (ArgumentString
== ValueBuffer
) {
651 BasePrintLibSPrint ((CHAR8
*) ValueBuffer
, MAXIMUM_VALUE_CHARACTERS
, 0, "%08X", Status
);
656 ArgumentString
= "\n\r";
662 // if the type is '%' or unknown, then print it to the screen
664 ArgumentString
= (CHAR8
*)&FormatCharacter
;
665 Flags
|= ARGUMENT_UNICODE
;
671 ArgumentString
= "\n\r";
675 ArgumentString
= (CHAR8
*)&FormatCharacter
;
676 Flags
|= ARGUMENT_UNICODE
;
681 // Retrieve the ArgumentString attriubutes
683 if ((Flags
& ARGUMENT_UNICODE
) != 0) {
684 ArgumentMask
= 0xffff;
685 BytesPerArgumentCharacter
= 2;
688 BytesPerArgumentCharacter
= 1;
690 if ((Flags
& ARGUMENT_REVERSED
) != 0) {
691 BytesPerArgumentCharacter
= -BytesPerArgumentCharacter
;
694 // Compute the number of characters in ArgumentString and store it in Count
695 // ArgumentString is either null-terminated, or it contains Precision characters
697 for (Count
= 0; Count
< Precision
|| ((Flags
& PRECISION
) == 0); Count
++) {
698 ArgumentCharacter
= ((ArgumentString
[Count
* BytesPerArgumentCharacter
] & 0xff) | ((ArgumentString
[Count
* BytesPerArgumentCharacter
+ 1]) << 8)) & ArgumentMask
;
699 if (ArgumentCharacter
== 0) {
705 if (Precision
< Count
) {
710 // Pad before the string
712 if ((Flags
& (PAD_TO_WIDTH
| LEFT_JUSTIFY
)) == (PAD_TO_WIDTH
)) {
713 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, Width
- Precision
, ' ', BytesPerOutputCharacter
);
718 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, Prefix
, BytesPerOutputCharacter
);
720 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, Precision
- Count
, '0', BytesPerOutputCharacter
);
722 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, Precision
- Count
, ' ', BytesPerOutputCharacter
);
724 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, Prefix
, BytesPerOutputCharacter
);
729 // Output the Prefix character if it is present
737 // Copy the string into the output buffer performing the required type conversions
739 while (Index
< Count
) {
740 ArgumentCharacter
= ((*ArgumentString
& 0xff) | (*(ArgumentString
+ 1) << 8)) & ArgumentMask
;
742 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, ArgumentCharacter
, BytesPerOutputCharacter
);
743 ArgumentString
+= BytesPerArgumentCharacter
;
751 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, ',', BytesPerOutputCharacter
);
758 // Pad after the string
760 if ((Flags
& (PAD_TO_WIDTH
| LEFT_JUSTIFY
)) == (PAD_TO_WIDTH
| LEFT_JUSTIFY
)) {
761 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, Width
- Precision
, ' ', BytesPerOutputCharacter
);
765 // Get the next character from the format string
767 Format
+= BytesPerFormatCharacter
;
770 // Get the next character from the format string
772 FormatCharacter
= ((*Format
& 0xff) | (*(Format
+ 1) << 8)) & FormatMask
;
776 // Null terminate the Unicode or ASCII string
778 BasePrintLibFillBuffer (Buffer
, EndBuffer
+ BytesPerOutputCharacter
, 1, 0, BytesPerOutputCharacter
);
780 // Make sure output buffer cannot contain more than PcdMaximumUnicodeStringLength
781 // Unicode characters if PcdMaximumUnicodeStringLength is not zero.
783 ASSERT ((((Flags
& OUTPUT_UNICODE
) == 0)) || (StrSize ((CHAR16
*) OriginalBuffer
) != 0));
785 // Make sure output buffer cannot contain more than PcdMaximumAsciiStringLength
786 // ASCII characters if PcdMaximumAsciiStringLength is not zero.
788 ASSERT ((((Flags
& OUTPUT_UNICODE
) != 0)) || (AsciiStrSize (OriginalBuffer
) != 0));
790 return ((Buffer
- OriginalBuffer
) / BytesPerOutputCharacter
);
794 Worker function that produces a Null-terminated string in an output buffer
795 based on a Null-terminated format string and variable argument list.
797 VSPrint function to process format and place the results in Buffer. Since a
798 VA_LIST is used this rountine allows the nesting of Vararg routines. Thus
799 this is the main print working routine
801 @param StartOfBuffer Character buffer to print the results of the parsing
803 @param BufferSize Maximum number of characters to put into buffer.
805 @param Flags Intial flags value.
806 Can only have FORMAT_UNICODE and OUTPUT_UNICODE set
807 @param FormatString Null-terminated format string.
808 @param ... The variable argument list.
810 @return Number of characters printed.
815 OUT CHAR8
*StartOfBuffer
,
818 IN CONST CHAR8
*FormatString
,
824 VA_START (Marker
, FormatString
);
825 return BasePrintLibVSPrint (StartOfBuffer
, BufferSize
, Flags
, FormatString
, Marker
);