TianoCore EDK2 master
Loading...
Searching...
No Matches
PrintLibInternal.c
Go to the documentation of this file.
1
9#include "PrintLibInternal.h"
10
11#define WARNING_STATUS_NUMBER 7
12#define ERROR_STATUS_NUMBER 35
13
14//
15// Safe print checks
16//
17#define RSIZE_MAX (PcdGet32 (PcdMaximumUnicodeStringLength))
18#define ASCII_RSIZE_MAX (PcdGet32 (PcdMaximumAsciiStringLength))
19
20#define SAFE_PRINT_CONSTRAINT_CHECK(Expression, RetVal) \
21 do { \
22 ASSERT (Expression); \
23 if (!(Expression)) { \
24 return RetVal; \
25 } \
26 } while (FALSE)
27
28GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexStr[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
29
30//
31// Longest string: RETURN_WARN_BUFFER_TOO_SMALL => 24 characters plus NUL byte
32//
33GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mWarningString[][24+1] = {
34 "Success", // RETURN_SUCCESS = 0
35 "Warning Unknown Glyph", // RETURN_WARN_UNKNOWN_GLYPH = 1
36 "Warning Delete Failure", // RETURN_WARN_DELETE_FAILURE = 2
37 "Warning Write Failure", // RETURN_WARN_WRITE_FAILURE = 3
38 "Warning Buffer Too Small", // RETURN_WARN_BUFFER_TOO_SMALL = 4
39 "Warning Stale Data", // RETURN_WARN_STALE_DATA = 5
40 "Warning File System", // RETURN_WARN_FILE_SYSTEM = 6
41 "Warning Reset Required", // RETURN_WARN_RESET_REQUIRED = 7
42};
43
44//
45// Longest string: RETURN_INCOMPATIBLE_VERSION => 20 characters plus NUL byte
46//
47GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mErrorString[][20+1] = {
48 "Load Error", // RETURN_LOAD_ERROR = 1 | MAX_BIT
49 "Invalid Parameter", // RETURN_INVALID_PARAMETER = 2 | MAX_BIT
50 "Unsupported", // RETURN_UNSUPPORTED = 3 | MAX_BIT
51 "Bad Buffer Size", // RETURN_BAD_BUFFER_SIZE = 4 | MAX_BIT
52 "Buffer Too Small", // RETURN_BUFFER_TOO_SMALL, = 5 | MAX_BIT
53 "Not Ready", // RETURN_NOT_READY = 6 | MAX_BIT
54 "Device Error", // RETURN_DEVICE_ERROR = 7 | MAX_BIT
55 "Write Protected", // RETURN_WRITE_PROTECTED = 8 | MAX_BIT
56 "Out of Resources", // RETURN_OUT_OF_RESOURCES = 9 | MAX_BIT
57 "Volume Corrupt", // RETURN_VOLUME_CORRUPTED = 10 | MAX_BIT
58 "Volume Full", // RETURN_VOLUME_FULL = 11 | MAX_BIT
59 "No Media", // RETURN_NO_MEDIA = 12 | MAX_BIT
60 "Media changed", // RETURN_MEDIA_CHANGED = 13 | MAX_BIT
61 "Not Found", // RETURN_NOT_FOUND = 14 | MAX_BIT
62 "Access Denied", // RETURN_ACCESS_DENIED = 15 | MAX_BIT
63 "No Response", // RETURN_NO_RESPONSE = 16 | MAX_BIT
64 "No mapping", // RETURN_NO_MAPPING = 17 | MAX_BIT
65 "Time out", // RETURN_TIMEOUT = 18 | MAX_BIT
66 "Not started", // RETURN_NOT_STARTED = 19 | MAX_BIT
67 "Already started", // RETURN_ALREADY_STARTED = 20 | MAX_BIT
68 "Aborted", // RETURN_ABORTED = 21 | MAX_BIT
69 "ICMP Error", // RETURN_ICMP_ERROR = 22 | MAX_BIT
70 "TFTP Error", // RETURN_TFTP_ERROR = 23 | MAX_BIT
71 "Protocol Error", // RETURN_PROTOCOL_ERROR = 24 | MAX_BIT
72 "Incompatible Version", // RETURN_INCOMPATIBLE_VERSION = 25 | MAX_BIT
73 "Security Violation", // RETURN_SECURITY_VIOLATION = 26 | MAX_BIT
74 "CRC Error", // RETURN_CRC_ERROR = 27 | MAX_BIT
75 "End of Media", // RETURN_END_OF_MEDIA = 28 | MAX_BIT
76 "Reserved (29)", // RESERVED = 29 | MAX_BIT
77 "Reserved (30)", // RESERVED = 30 | MAX_BIT
78 "End of File", // RETURN_END_OF_FILE = 31 | MAX_BIT
79 "Invalid Language", // RETURN_INVALID_LANGUAGE = 32 | MAX_BIT
80 "Compromised Data", // RETURN_COMPROMISED_DATA = 33 | MAX_BIT
81 "IP Address Conflict", // RETURN_IP_ADDRESS_CONFLICT = 34 | MAX_BIT
82 "HTTP Error" // RETURN_HTTP_ERROR = 35 | MAX_BIT
83};
84
101CHAR8 *
103 OUT CHAR8 *Buffer,
104 IN CHAR8 *EndBuffer,
105 IN INTN Length,
106 IN UINTN Character,
107 IN INTN Increment
108 )
109{
110 INTN Index;
111
112 for (Index = 0; Index < Length && Buffer < EndBuffer; Index++) {
113 *Buffer = (CHAR8)Character;
114 if (Increment != 1) {
115 *(Buffer + 1) = (CHAR8)(Character >> 8);
116 }
117
118 Buffer += Increment;
119 }
120
121 return Buffer;
122}
123
136CHAR8 *
138 IN OUT CHAR8 *Buffer,
139 IN INT64 Value,
140 IN UINTN Radix
141 )
142{
143 UINT32 Remainder;
144
145 //
146 // Loop to convert one digit at a time in reverse order
147 //
148 *Buffer = 0;
149 do {
150 Value = (INT64)DivU64x32Remainder ((UINT64)Value, (UINT32)Radix, &Remainder);
151 *(++Buffer) = mHexStr[Remainder];
152 } while (Value != 0);
153
154 //
155 // Return pointer of the end of filled buffer.
156 //
157 return Buffer;
158}
159
198UINTN
200 IN OUT CHAR8 *Buffer,
201 IN UINTN Flags,
202 IN INT64 Value,
203 IN UINTN Width,
204 IN UINTN Increment
205 )
206{
207 CHAR8 *OriginalBuffer;
208 CHAR8 *EndBuffer;
209 CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];
210 CHAR8 *ValueBufferPtr;
211 UINTN Count;
212 UINTN Digits;
213 UINTN Index;
214 UINTN Radix;
215
216 //
217 // Make sure Buffer is not NULL and Width < MAXIMUM
218 //
219 ASSERT (Buffer != NULL);
220 ASSERT (Width < MAXIMUM_VALUE_CHARACTERS);
221 //
222 // Make sure Flags can only contain supported bits.
223 //
224 ASSERT ((Flags & ~(LEFT_JUSTIFY | COMMA_TYPE | PREFIX_ZERO | RADIX_HEX)) == 0);
225
226 //
227 // If both COMMA_TYPE and RADIX_HEX are set, then ASSERT ()
228 //
229 ASSERT (((Flags & COMMA_TYPE) == 0) || ((Flags & RADIX_HEX) == 0));
230
231 OriginalBuffer = Buffer;
232
233 //
234 // Width is 0 or COMMA_TYPE is set, PREFIX_ZERO is ignored.
235 //
236 if ((Width == 0) || ((Flags & COMMA_TYPE) != 0)) {
237 Flags &= ~((UINTN)PREFIX_ZERO);
238 }
239
240 //
241 // If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
242 //
243 if (Width == 0) {
244 Width = MAXIMUM_VALUE_CHARACTERS - 1;
245 }
246
247 //
248 // Set the tag for the end of the input Buffer.
249 //
250 EndBuffer = Buffer + Width * Increment;
251
252 //
253 // Convert decimal negative
254 //
255 if ((Value < 0) && ((Flags & RADIX_HEX) == 0)) {
256 Value = -Value;
257 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, '-', Increment);
258 Width--;
259 }
260
261 //
262 // Count the length of the value string.
263 //
264 Radix = ((Flags & RADIX_HEX) == 0) ? 10 : 16;
265 ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, Value, Radix);
266 Count = ValueBufferPtr - ValueBuffer;
267
268 //
269 // Append Zero
270 //
271 if ((Flags & PREFIX_ZERO) != 0) {
272 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Count, '0', Increment);
273 }
274
275 //
276 // Print Comma type for every 3 characters
277 //
278 Digits = Count % 3;
279 if (Digits != 0) {
280 Digits = 3 - Digits;
281 }
282
283 for (Index = 0; Index < Count; Index++) {
284 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, *ValueBufferPtr--, Increment);
285 if ((Flags & COMMA_TYPE) != 0) {
286 Digits++;
287 if (Digits == 3) {
288 Digits = 0;
289 if ((Index + 1) < Count) {
290 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', Increment);
291 }
292 }
293 }
294 }
295
296 //
297 // Print Null-terminator
298 //
299 BasePrintLibFillBuffer (Buffer, EndBuffer + Increment, 1, 0, Increment);
300
301 return ((Buffer - OriginalBuffer) / Increment);
302}
303
355RETURN_STATUS
357 IN OUT CHAR8 *Buffer,
358 IN UINTN BufferSize,
359 IN UINTN Flags,
360 IN INT64 Value,
361 IN UINTN Width,
362 IN UINTN Increment
363 )
364{
365 CHAR8 *EndBuffer;
366 CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];
367 CHAR8 *ValueBufferPtr;
368 UINTN Count;
369 UINTN Digits;
370 UINTN Index;
371 UINTN Radix;
372
373 //
374 // 1. Buffer shall not be a null pointer.
375 //
376 SAFE_PRINT_CONSTRAINT_CHECK ((Buffer != NULL), RETURN_INVALID_PARAMETER);
377
378 //
379 // 2. BufferSize shall not be greater than (RSIZE_MAX * sizeof (CHAR16)) for
380 // Unicode output string or shall not be greater than ASCII_RSIZE_MAX for
381 // Ascii output string.
382 //
383 if (Increment == 1) {
384 //
385 // Ascii output string
386 //
387 if (ASCII_RSIZE_MAX != 0) {
388 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
389 }
390 } else {
391 //
392 // Unicode output string
393 //
394 if (RSIZE_MAX != 0) {
395 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize <= RSIZE_MAX * sizeof (CHAR16) + 1), RETURN_INVALID_PARAMETER);
396 }
397 }
398
399 //
400 // 3. Flags shall be set properly.
401 //
402 SAFE_PRINT_CONSTRAINT_CHECK (((Flags & ~(LEFT_JUSTIFY | COMMA_TYPE | PREFIX_ZERO | RADIX_HEX)) == 0), RETURN_INVALID_PARAMETER);
403 SAFE_PRINT_CONSTRAINT_CHECK ((((Flags & COMMA_TYPE) == 0) || ((Flags & RADIX_HEX) == 0)), RETURN_INVALID_PARAMETER);
404
405 //
406 // 4. Width shall be smaller than MAXIMUM_VALUE_CHARACTERS.
407 //
408 SAFE_PRINT_CONSTRAINT_CHECK ((Width < MAXIMUM_VALUE_CHARACTERS), RETURN_INVALID_PARAMETER);
409
410 //
411 // Width is 0 or COMMA_TYPE is set, PREFIX_ZERO is ignored.
412 //
413 if ((Width == 0) || ((Flags & COMMA_TYPE) != 0)) {
414 Flags &= ~((UINTN)PREFIX_ZERO);
415 }
416
417 //
418 // If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
419 //
420 if (Width == 0) {
421 Width = MAXIMUM_VALUE_CHARACTERS - 1;
422 }
423
424 //
425 // Count the characters of the output string.
426 //
427 Count = 0;
428 Radix = ((Flags & RADIX_HEX) == 0) ? 10 : 16;
429
430 if ((Flags & PREFIX_ZERO) != 0) {
431 Count = Width;
432 } else {
433 if ((Value < 0) && ((Flags & RADIX_HEX) == 0)) {
434 Count++; // minus sign
435 ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, -Value, Radix);
436 } else {
437 ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, Value, Radix);
438 }
439
440 Digits = ValueBufferPtr - ValueBuffer;
441 Count += Digits;
442
443 if ((Flags & COMMA_TYPE) != 0) {
444 Count += (Digits - 1) / 3; // commas
445 }
446 }
447
448 Width = MIN (Count, Width);
449
450 //
451 // 5. BufferSize shall be large enough to hold the converted string.
452 //
453 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize >= (Width + 1) * Increment), RETURN_BUFFER_TOO_SMALL);
454
455 //
456 // Set the tag for the end of the input Buffer.
457 //
458 EndBuffer = Buffer + Width * Increment;
459
460 //
461 // Convert decimal negative
462 //
463 if ((Value < 0) && ((Flags & RADIX_HEX) == 0)) {
464 Value = -Value;
465 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, '-', Increment);
466 Width--;
467 }
468
469 //
470 // Count the length of the value string.
471 //
472 ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, Value, Radix);
473 Count = ValueBufferPtr - ValueBuffer;
474
475 //
476 // Append Zero
477 //
478 if ((Flags & PREFIX_ZERO) != 0) {
479 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Count, '0', Increment);
480 }
481
482 //
483 // Print Comma type for every 3 characters
484 //
485 Digits = Count % 3;
486 if (Digits != 0) {
487 Digits = 3 - Digits;
488 }
489
490 for (Index = 0; Index < Count; Index++) {
491 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, *ValueBufferPtr--, Increment);
492 if ((Flags & COMMA_TYPE) != 0) {
493 Digits++;
494 if (Digits == 3) {
495 Digits = 0;
496 if ((Index + 1) < Count) {
497 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', Increment);
498 }
499 }
500 }
501 }
502
503 //
504 // Print Null-terminator
505 //
506 BasePrintLibFillBuffer (Buffer, EndBuffer + Increment, 1, 0, Increment);
507
508 return RETURN_SUCCESS;
509}
510
539UINTN
541 OUT CHAR8 *Buffer,
542 IN UINTN BufferSize,
543 IN UINTN Flags,
544 IN CONST CHAR8 *Format,
545 IN VA_LIST VaListMarker OPTIONAL,
546 IN BASE_LIST BaseListMarker OPTIONAL
547 )
548{
549 CHAR8 *OriginalBuffer;
550 CHAR8 *EndBuffer;
551 CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];
552 UINT32 BytesPerOutputCharacter;
553 UINTN BytesPerFormatCharacter;
554 UINTN FormatMask;
555 UINTN FormatCharacter;
556 UINTN Width;
557 UINTN Precision;
558 INT64 Value;
559 CONST CHAR8 *ArgumentString;
560 UINTN Character;
561 GUID *TmpGuid;
562 TIME *TmpTime;
563 UINTN Count;
564 UINTN ArgumentMask;
565 INTN BytesPerArgumentCharacter;
566 UINTN ArgumentCharacter;
567 BOOLEAN Done;
568 UINTN Index;
569 CHAR8 Prefix;
570 BOOLEAN ZeroPad;
571 BOOLEAN Comma;
572 UINTN Digits;
573 UINTN Radix;
574 RETURN_STATUS Status;
575 UINT32 GuidData1;
576 UINT16 GuidData2;
577 UINT16 GuidData3;
578 UINTN LengthToReturn;
579
580 //
581 // If you change this code be sure to match the 2 versions of this function.
582 // Nearly identical logic is found in the BasePrintLib and
583 // DxePrintLibPrint2Protocol (both PrintLib instances).
584 //
585
586 //
587 // 1. Buffer shall not be a null pointer when both BufferSize > 0 and
588 // COUNT_ONLY_NO_PRINT is not set in Flags.
589 //
590 if ((BufferSize > 0) && ((Flags & COUNT_ONLY_NO_PRINT) == 0)) {
591 SAFE_PRINT_CONSTRAINT_CHECK ((Buffer != NULL), 0);
592 }
593
594 //
595 // 2. Format shall not be a null pointer when BufferSize > 0 or when
596 // COUNT_ONLY_NO_PRINT is set in Flags.
597 //
598 if ((BufferSize > 0) || ((Flags & COUNT_ONLY_NO_PRINT) != 0)) {
599 SAFE_PRINT_CONSTRAINT_CHECK ((Format != NULL), 0);
600 }
601
602 //
603 // 3. BufferSize shall not be greater than RSIZE_MAX for Unicode output or
604 // ASCII_RSIZE_MAX for Ascii output.
605 //
606 if ((Flags & OUTPUT_UNICODE) != 0) {
607 if (RSIZE_MAX != 0) {
608 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize <= RSIZE_MAX), 0);
609 }
610
611 BytesPerOutputCharacter = 2;
612 } else {
613 if (ASCII_RSIZE_MAX != 0) {
614 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize <= ASCII_RSIZE_MAX), 0);
615 }
616
617 BytesPerOutputCharacter = 1;
618 }
619
620 //
621 // 4. Format shall not contain more than RSIZE_MAX Unicode characters or
622 // ASCII_RSIZE_MAX Ascii characters.
623 //
624 if ((Flags & FORMAT_UNICODE) != 0) {
625 if (RSIZE_MAX != 0) {
626 SAFE_PRINT_CONSTRAINT_CHECK ((StrnLenS ((CHAR16 *)Format, RSIZE_MAX + 1) <= RSIZE_MAX), 0);
627 }
628
629 BytesPerFormatCharacter = 2;
630 FormatMask = 0xffff;
631 } else {
632 if (ASCII_RSIZE_MAX != 0) {
633 SAFE_PRINT_CONSTRAINT_CHECK ((AsciiStrnLenS (Format, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), 0);
634 }
635
636 BytesPerFormatCharacter = 1;
637 FormatMask = 0xff;
638 }
639
640 if ((Flags & COUNT_ONLY_NO_PRINT) != 0) {
641 if (BufferSize == 0) {
642 Buffer = NULL;
643 }
644 } else {
645 //
646 // We can run without a Buffer for counting only.
647 //
648 if (BufferSize == 0) {
649 return 0;
650 }
651 }
652
653 LengthToReturn = 0;
654 EndBuffer = NULL;
655 OriginalBuffer = NULL;
656
657 //
658 // Reserve space for the Null terminator.
659 //
660 if (Buffer != NULL) {
661 BufferSize--;
662 OriginalBuffer = Buffer;
663
664 //
665 // Set the tag for the end of the input Buffer.
666 //
667 EndBuffer = Buffer + BufferSize * BytesPerOutputCharacter;
668 }
669
670 //
671 // Get the first character from the format string
672 //
673 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;
674
675 //
676 // Loop until the end of the format string is reached or the output buffer is full
677 //
678 while (FormatCharacter != 0) {
679 if ((Buffer != NULL) && (Buffer >= EndBuffer)) {
680 break;
681 }
682
683 //
684 // Clear all the flag bits except those that may have been passed in
685 //
686 Flags &= (UINTN)(OUTPUT_UNICODE | FORMAT_UNICODE | COUNT_ONLY_NO_PRINT);
687
688 //
689 // Set the default width to zero, and the default precision to 1
690 //
691 Width = 0;
692 Precision = 1;
693 Prefix = 0;
694 Comma = FALSE;
695 ZeroPad = FALSE;
696 Count = 0;
697 Digits = 0;
698
699 switch (FormatCharacter) {
700 case '%':
701 //
702 // Parse Flags and Width
703 //
704 for (Done = FALSE; !Done; ) {
705 Format += BytesPerFormatCharacter;
706 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;
707 switch (FormatCharacter) {
708 case '.':
709 Flags |= PRECISION;
710 break;
711 case '-':
712 Flags |= LEFT_JUSTIFY;
713 break;
714 case '+':
715 Flags |= PREFIX_SIGN;
716 break;
717 case ' ':
718 Flags |= PREFIX_BLANK;
719 break;
720 case ',':
721 Flags |= COMMA_TYPE;
722 break;
723 case 'L':
724 case 'l':
725 Flags |= LONG_TYPE;
726 break;
727 case '*':
728 if ((Flags & PRECISION) == 0) {
729 Flags |= PAD_TO_WIDTH;
730 if (BaseListMarker == NULL) {
731 Width = VA_ARG (VaListMarker, UINTN);
732 } else {
733 Width = BASE_ARG (BaseListMarker, UINTN);
734 }
735 } else {
736 if (BaseListMarker == NULL) {
737 Precision = VA_ARG (VaListMarker, UINTN);
738 } else {
739 Precision = BASE_ARG (BaseListMarker, UINTN);
740 }
741 }
742
743 break;
744 case '0':
745 if ((Flags & PRECISION) == 0) {
746 Flags |= PREFIX_ZERO;
747 }
748
749 case '1':
750 case '2':
751 case '3':
752 case '4':
753 case '5':
754 case '6':
755 case '7':
756 case '8':
757 case '9':
758 for (Count = 0; ((FormatCharacter >= '0') && (FormatCharacter <= '9')); ) {
759 Count = (Count * 10) + FormatCharacter - '0';
760 Format += BytesPerFormatCharacter;
761 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;
762 }
763
764 Format -= BytesPerFormatCharacter;
765 if ((Flags & PRECISION) == 0) {
766 Flags |= PAD_TO_WIDTH;
767 Width = Count;
768 } else {
769 Precision = Count;
770 }
771
772 break;
773
774 case '\0':
775 //
776 // Make no output if Format string terminates unexpectedly when
777 // looking up for flag, width, precision and type.
778 //
779 Format -= BytesPerFormatCharacter;
780 Precision = 0;
781 //
782 // break skipped on purpose.
783 //
784 default:
785 Done = TRUE;
786 break;
787 }
788 }
789
790 //
791 // Handle each argument type
792 //
793 switch (FormatCharacter) {
794 case 'p':
795 //
796 // Flag space, +, 0, L & l are invalid for type p.
797 //
798 Flags &= ~((UINTN)(PREFIX_BLANK | PREFIX_SIGN | PREFIX_ZERO | LONG_TYPE));
799 if (sizeof (VOID *) > 4) {
800 Flags |= LONG_TYPE;
801 }
802
803 //
804 // break skipped on purpose
805 //
806 case 'X':
807 Flags |= PREFIX_ZERO;
808 //
809 // break skipped on purpose
810 //
811 case 'x':
812 Flags |= RADIX_HEX;
813 //
814 // break skipped on purpose
815 //
816 case 'u':
817 if ((Flags & RADIX_HEX) == 0) {
818 Flags &= ~((UINTN)(PREFIX_SIGN));
819 Flags |= UNSIGNED_TYPE;
820 }
821
822 //
823 // break skipped on purpose
824 //
825 case 'd':
826 if ((Flags & LONG_TYPE) == 0) {
827 //
828 // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
829 // This assumption is made so the format string definition is compatible with the ANSI C
830 // Specification for formatted strings. It is recommended that the Base Types be used
831 // everywhere, but in this one case, compliance with ANSI C is more important, and
832 // provides an implementation that is compatible with that largest possible set of CPU
833 // architectures. This is why the type "int" is used in this one case.
834 //
835 if (BaseListMarker == NULL) {
836 Value = VA_ARG (VaListMarker, int);
837 } else {
838 Value = BASE_ARG (BaseListMarker, int);
839 }
840 } else {
841 if (BaseListMarker == NULL) {
842 Value = VA_ARG (VaListMarker, INT64);
843 } else {
844 Value = BASE_ARG (BaseListMarker, INT64);
845 }
846 }
847
848 if ((Flags & PREFIX_BLANK) != 0) {
849 Prefix = ' ';
850 }
851
852 if ((Flags & PREFIX_SIGN) != 0) {
853 Prefix = '+';
854 }
855
856 if ((Flags & COMMA_TYPE) != 0) {
857 Comma = TRUE;
858 }
859
860 if ((Flags & RADIX_HEX) == 0) {
861 Radix = 10;
862 if (Comma) {
863 Flags &= ~((UINTN)PREFIX_ZERO);
864 Precision = 1;
865 }
866
867 if ((Value < 0) && ((Flags & UNSIGNED_TYPE) == 0)) {
868 Flags |= PREFIX_SIGN;
869 Prefix = '-';
870 Value = -Value;
871 } else if (((Flags & UNSIGNED_TYPE) != 0) && ((Flags & LONG_TYPE) == 0)) {
872 //
873 // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
874 // This assumption is made so the format string definition is compatible with the ANSI C
875 // Specification for formatted strings. It is recommended that the Base Types be used
876 // everywhere, but in this one case, compliance with ANSI C is more important, and
877 // provides an implementation that is compatible with that largest possible set of CPU
878 // architectures. This is why the type "unsigned int" is used in this one case.
879 //
880 Value = (unsigned int)Value;
881 }
882 } else {
883 Radix = 16;
884 Comma = FALSE;
885 if (((Flags & LONG_TYPE) == 0) && (Value < 0)) {
886 //
887 // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
888 // This assumption is made so the format string definition is compatible with the ANSI C
889 // Specification for formatted strings. It is recommended that the Base Types be used
890 // everywhere, but in this one case, compliance with ANSI C is more important, and
891 // provides an implementation that is compatible with that largest possible set of CPU
892 // architectures. This is why the type "unsigned int" is used in this one case.
893 //
894 Value = (unsigned int)Value;
895 }
896 }
897
898 //
899 // Convert Value to a reversed string
900 //
901 Count = BasePrintLibValueToString (ValueBuffer, Value, Radix) - ValueBuffer;
902 if ((Value == 0) && (Precision == 0)) {
903 Count = 0;
904 }
905
906 ArgumentString = (CHAR8 *)ValueBuffer + Count;
907
908 Digits = Count % 3;
909 if (Digits != 0) {
910 Digits = 3 - Digits;
911 }
912
913 if (Comma && (Count != 0)) {
914 Count += ((Count - 1) / 3);
915 }
916
917 if (Prefix != 0) {
918 Count++;
919 Precision++;
920 }
921
922 Flags |= ARGUMENT_REVERSED;
923 ZeroPad = TRUE;
924 if ((Flags & PREFIX_ZERO) != 0) {
925 if ((Flags & LEFT_JUSTIFY) == 0) {
926 if ((Flags & PAD_TO_WIDTH) != 0) {
927 if ((Flags & PRECISION) == 0) {
928 Precision = Width;
929 }
930 }
931 }
932 }
933
934 break;
935
936 case 's':
937 case 'S':
938 Flags |= ARGUMENT_UNICODE;
939 //
940 // break skipped on purpose
941 //
942 case 'a':
943 if (BaseListMarker == NULL) {
944 ArgumentString = VA_ARG (VaListMarker, CHAR8 *);
945 } else {
946 ArgumentString = BASE_ARG (BaseListMarker, CHAR8 *);
947 }
948
949 if (ArgumentString == NULL) {
950 Flags &= ~((UINTN)ARGUMENT_UNICODE);
951 ArgumentString = "<null string>";
952 }
953
954 //
955 // Set the default precision for string to be zero if not specified.
956 //
957 if ((Flags & PRECISION) == 0) {
958 Precision = 0;
959 }
960
961 break;
962
963 case 'c':
964 if (BaseListMarker == NULL) {
965 Character = VA_ARG (VaListMarker, UINTN) & 0xffff;
966 } else {
967 Character = BASE_ARG (BaseListMarker, UINTN) & 0xffff;
968 }
969
970 ArgumentString = (CHAR8 *)&Character;
971 Flags |= ARGUMENT_UNICODE;
972 break;
973
974 case 'g':
975 if (BaseListMarker == NULL) {
976 TmpGuid = VA_ARG (VaListMarker, GUID *);
977 } else {
978 TmpGuid = BASE_ARG (BaseListMarker, GUID *);
979 }
980
981 if (TmpGuid == NULL) {
982 ArgumentString = "<null guid>";
983 } else {
984 GuidData1 = ReadUnaligned32 (&(TmpGuid->Data1));
985 GuidData2 = ReadUnaligned16 (&(TmpGuid->Data2));
986 GuidData3 = ReadUnaligned16 (&(TmpGuid->Data3));
988 ValueBuffer,
990 0,
991 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
992 GuidData1,
993 GuidData2,
994 GuidData3,
995 TmpGuid->Data4[0],
996 TmpGuid->Data4[1],
997 TmpGuid->Data4[2],
998 TmpGuid->Data4[3],
999 TmpGuid->Data4[4],
1000 TmpGuid->Data4[5],
1001 TmpGuid->Data4[6],
1002 TmpGuid->Data4[7]
1003 );
1004 ArgumentString = ValueBuffer;
1005 }
1006
1007 break;
1008
1009 case 't':
1010 if (BaseListMarker == NULL) {
1011 TmpTime = VA_ARG (VaListMarker, TIME *);
1012 } else {
1013 TmpTime = BASE_ARG (BaseListMarker, TIME *);
1014 }
1015
1016 if (TmpTime == NULL) {
1017 ArgumentString = "<null time>";
1018 } else {
1020 ValueBuffer,
1022 0,
1023 "%02d/%02d/%04d %02d:%02d",
1024 TmpTime->Month,
1025 TmpTime->Day,
1026 TmpTime->Year,
1027 TmpTime->Hour,
1028 TmpTime->Minute
1029 );
1030 ArgumentString = ValueBuffer;
1031 }
1032
1033 break;
1034
1035 case 'r':
1036 if (BaseListMarker == NULL) {
1037 Status = VA_ARG (VaListMarker, RETURN_STATUS);
1038 } else {
1039 Status = BASE_ARG (BaseListMarker, RETURN_STATUS);
1040 }
1041
1042 ArgumentString = ValueBuffer;
1043 if (RETURN_ERROR (Status)) {
1044 //
1045 // Clear error bit
1046 //
1047 Index = Status & ~MAX_BIT;
1048 if ((Index > 0) && (Index <= ERROR_STATUS_NUMBER)) {
1049 ArgumentString = mErrorString[Index - 1];
1050 }
1051 } else {
1052 Index = Status;
1053 if (Index <= WARNING_STATUS_NUMBER) {
1054 ArgumentString = mWarningString[Index];
1055 }
1056 }
1057
1058 if (ArgumentString == ValueBuffer) {
1059 BasePrintLibSPrint ((CHAR8 *)ValueBuffer, MAXIMUM_VALUE_CHARACTERS, 0, "%08X", Status);
1060 }
1061
1062 break;
1063
1064 case '\r':
1065 Format += BytesPerFormatCharacter;
1066 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;
1067 if (FormatCharacter == '\n') {
1068 //
1069 // Translate '\r\n' to '\r\n'
1070 //
1071 ArgumentString = "\r\n";
1072 } else {
1073 //
1074 // Translate '\r' to '\r'
1075 //
1076 ArgumentString = "\r";
1077 Format -= BytesPerFormatCharacter;
1078 }
1079
1080 break;
1081
1082 case '\n':
1083 //
1084 // Translate '\n' to '\r\n' and '\n\r' to '\r\n'
1085 //
1086 ArgumentString = "\r\n";
1087 Format += BytesPerFormatCharacter;
1088 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;
1089 if (FormatCharacter != '\r') {
1090 Format -= BytesPerFormatCharacter;
1091 }
1092
1093 break;
1094
1095 case '%':
1096 default:
1097 //
1098 // if the type is '%' or unknown, then print it to the screen
1099 //
1100 ArgumentString = (CHAR8 *)&FormatCharacter;
1101 Flags |= ARGUMENT_UNICODE;
1102 break;
1103 }
1104
1105 break;
1106
1107 case '\r':
1108 Format += BytesPerFormatCharacter;
1109 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;
1110 if (FormatCharacter == '\n') {
1111 //
1112 // Translate '\r\n' to '\r\n'
1113 //
1114 ArgumentString = "\r\n";
1115 } else {
1116 //
1117 // Translate '\r' to '\r'
1118 //
1119 ArgumentString = "\r";
1120 Format -= BytesPerFormatCharacter;
1121 }
1122
1123 break;
1124
1125 case '\n':
1126 //
1127 // Translate '\n' to '\r\n' and '\n\r' to '\r\n'
1128 //
1129 ArgumentString = "\r\n";
1130 Format += BytesPerFormatCharacter;
1131 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;
1132 if (FormatCharacter != '\r') {
1133 Format -= BytesPerFormatCharacter;
1134 }
1135
1136 break;
1137
1138 default:
1139 ArgumentString = (CHAR8 *)&FormatCharacter;
1140 Flags |= ARGUMENT_UNICODE;
1141 break;
1142 }
1143
1144 //
1145 // Retrieve the ArgumentString attriubutes
1146 //
1147 if ((Flags & ARGUMENT_UNICODE) != 0) {
1148 ArgumentMask = 0xffff;
1149 BytesPerArgumentCharacter = 2;
1150 } else {
1151 ArgumentMask = 0xff;
1152 BytesPerArgumentCharacter = 1;
1153 }
1154
1155 if ((Flags & ARGUMENT_REVERSED) != 0) {
1156 BytesPerArgumentCharacter = -BytesPerArgumentCharacter;
1157 } else {
1158 //
1159 // Compute the number of characters in ArgumentString and store it in Count
1160 // ArgumentString is either null-terminated, or it contains Precision characters
1161 //
1162 for (Count = 0;
1163 (ArgumentString[Count * BytesPerArgumentCharacter] != '\0' ||
1164 (BytesPerArgumentCharacter > 1 &&
1165 ArgumentString[Count * BytesPerArgumentCharacter + 1] != '\0')) &&
1166 (Count < Precision || ((Flags & PRECISION) == 0));
1167 Count++)
1168 {
1169 ArgumentCharacter = ((ArgumentString[Count * BytesPerArgumentCharacter] & 0xff) | ((ArgumentString[Count * BytesPerArgumentCharacter + 1]) << 8)) & ArgumentMask;
1170 if (ArgumentCharacter == 0) {
1171 break;
1172 }
1173 }
1174 }
1175
1176 if (Precision < Count) {
1177 Precision = Count;
1178 }
1179
1180 //
1181 // Pad before the string
1182 //
1183 if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH)) {
1184 LengthToReturn += ((Width - Precision) * BytesPerOutputCharacter);
1185 if (((Flags & COUNT_ONLY_NO_PRINT) == 0) && (Buffer != NULL)) {
1186 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);
1187 }
1188 }
1189
1190 if (ZeroPad) {
1191 if (Prefix != 0) {
1192 LengthToReturn += (1 * BytesPerOutputCharacter);
1193 if (((Flags & COUNT_ONLY_NO_PRINT) == 0) && (Buffer != NULL)) {
1194 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);
1195 }
1196 }
1197
1198 LengthToReturn += ((Precision - Count) * BytesPerOutputCharacter);
1199 if (((Flags & COUNT_ONLY_NO_PRINT) == 0) && (Buffer != NULL)) {
1200 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, '0', BytesPerOutputCharacter);
1201 }
1202 } else {
1203 LengthToReturn += ((Precision - Count) * BytesPerOutputCharacter);
1204 if (((Flags & COUNT_ONLY_NO_PRINT) == 0) && (Buffer != NULL)) {
1205 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, ' ', BytesPerOutputCharacter);
1206 }
1207
1208 if (Prefix != 0) {
1209 LengthToReturn += (1 * BytesPerOutputCharacter);
1210 if (((Flags & COUNT_ONLY_NO_PRINT) == 0) && (Buffer != NULL)) {
1211 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);
1212 }
1213 }
1214 }
1215
1216 //
1217 // Output the Prefix character if it is present
1218 //
1219 Index = 0;
1220 if (Prefix != 0) {
1221 Index++;
1222 }
1223
1224 //
1225 // Copy the string into the output buffer performing the required type conversions
1226 //
1227 while (Index < Count &&
1228 (ArgumentString[0] != '\0' ||
1229 (BytesPerArgumentCharacter > 1 && ArgumentString[1] != '\0')))
1230 {
1231 ArgumentCharacter = ((*ArgumentString & 0xff) | (((UINT8)*(ArgumentString + 1)) << 8)) & ArgumentMask;
1232
1233 LengthToReturn += (1 * BytesPerOutputCharacter);
1234 if (((Flags & COUNT_ONLY_NO_PRINT) == 0) && (Buffer != NULL)) {
1235 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ArgumentCharacter, BytesPerOutputCharacter);
1236 }
1237
1238 ArgumentString += BytesPerArgumentCharacter;
1239 Index++;
1240 if (Comma) {
1241 Digits++;
1242 if (Digits == 3) {
1243 Digits = 0;
1244 Index++;
1245 if (Index < Count) {
1246 LengthToReturn += (1 * BytesPerOutputCharacter);
1247 if (((Flags & COUNT_ONLY_NO_PRINT) == 0) && (Buffer != NULL)) {
1248 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', BytesPerOutputCharacter);
1249 }
1250 }
1251 }
1252 }
1253 }
1254
1255 //
1256 // Pad after the string
1257 //
1258 if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH | LEFT_JUSTIFY)) {
1259 LengthToReturn += ((Width - Precision) * BytesPerOutputCharacter);
1260 if (((Flags & COUNT_ONLY_NO_PRINT) == 0) && (Buffer != NULL)) {
1261 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);
1262 }
1263 }
1264
1265 //
1266 // Get the next character from the format string
1267 //
1268 Format += BytesPerFormatCharacter;
1269
1270 //
1271 // Get the next character from the format string
1272 //
1273 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;
1274 }
1275
1276 if ((Flags & COUNT_ONLY_NO_PRINT) != 0) {
1277 return (LengthToReturn / BytesPerOutputCharacter);
1278 }
1279
1280 ASSERT (Buffer != NULL);
1281 //
1282 // Null terminate the Unicode or ASCII string
1283 //
1284 BasePrintLibFillBuffer (Buffer, EndBuffer + BytesPerOutputCharacter, 1, 0, BytesPerOutputCharacter);
1285
1286 return ((Buffer - OriginalBuffer) / BytesPerOutputCharacter);
1287}
1288
1309UINTN
1310EFIAPI
1312 OUT CHAR8 *StartOfBuffer,
1313 IN UINTN BufferSize,
1314 IN UINTN Flags,
1315 IN CONST CHAR8 *FormatString,
1316 ...
1317 )
1318{
1319 VA_LIST Marker;
1320 UINTN NumberOfPrinted;
1321
1322 VA_START (Marker, FormatString);
1323 NumberOfPrinted = BasePrintLibSPrintMarker (StartOfBuffer, BufferSize, Flags, FormatString, Marker, NULL);
1324 VA_END (Marker);
1325 return NumberOfPrinted;
1326}
UINT64 UINTN
INT64 INTN
UINTN EFIAPI AsciiStrnLenS(IN CONST CHAR8 *String, IN UINTN MaxSize)
Definition: SafeString.c:1696
UINT16 EFIAPI ReadUnaligned16(IN CONST UINT16 *Buffer)
Definition: Unaligned.c:29
UINTN EFIAPI StrnLenS(IN CONST CHAR16 *String, IN UINTN MaxSize)
Definition: SafeString.c:119
UINT64 EFIAPI DivU64x32Remainder(IN UINT64 Dividend, IN UINT32 Divisor, OUT UINT32 *Remainder OPTIONAL)
UINT32 EFIAPI ReadUnaligned32(IN CONST UINT32 *Buffer)
Definition: Unaligned.c:145
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define RETURN_BUFFER_TOO_SMALL
Definition: Base.h:1093
#define RETURN_ERROR(StatusCode)
Definition: Base.h:1061
#define MIN(a, b)
Definition: Base.h:1007
#define VA_ARG(Marker, TYPE)
Definition: Base.h:679
#define BASE_ARG(Marker, TYPE)
Definition: Base.h:738
#define VA_START(Marker, Parameter)
Definition: Base.h:661
#define RETURN_SUCCESS
Definition: Base.h:1066
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
CHAR8 * VA_LIST
Definition: Base.h:643
#define IN
Definition: Base.h:279
UINTN * BASE_LIST
Definition: Base.h:711
#define OUT
Definition: Base.h:284
#define RETURN_INVALID_PARAMETER
Definition: Base.h:1076
#define GLOBAL_REMOVE_IF_UNREFERENCED
Definition: Base.h:48
#define VA_END(Marker)
Definition: Base.h:691
#define MAXIMUM_VALUE_CHARACTERS
Definition: PrintLib.h:189
#define LEFT_JUSTIFY
Definition: PrintLib.h:195
CHAR8 * BasePrintLibValueToString(IN OUT CHAR8 *Buffer, IN INT64 Value, IN UINTN Radix)
CHAR8 * BasePrintLibFillBuffer(OUT CHAR8 *Buffer, IN CHAR8 *EndBuffer, IN INTN Length, IN UINTN Character, IN INTN Increment)
UINTN EFIAPI BasePrintLibSPrint(OUT CHAR8 *StartOfBuffer, IN UINTN BufferSize, IN UINTN Flags, IN CONST CHAR8 *FormatString,...)
RETURN_STATUS BasePrintLibConvertValueToStringS(IN OUT CHAR8 *Buffer, IN UINTN BufferSize, IN UINTN Flags, IN INT64 Value, IN UINTN Width, IN UINTN Increment)
UINTN BasePrintLibConvertValueToString(IN OUT CHAR8 *Buffer, IN UINTN Flags, IN INT64 Value, IN UINTN Width, IN UINTN Increment)
UINTN BasePrintLibSPrintMarker(OUT CHAR8 *Buffer, IN UINTN BufferSize, IN UINTN Flags, IN CONST CHAR8 *Format, IN VA_LIST VaListMarker OPTIONAL, IN BASE_LIST BaseListMarker OPTIONAL)
Definition: Base.h:213