3 Copyright (c) 2004, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Basic Ascii AvSPrintf() function named AvSPrint(). AvSPrint() enables very
19 simple implemenation of debug prints.
21 You can not Print more than PEI_LIB_MAX_PRINT_BUFFER characters at a
22 time. This makes the implementation very simple.
24 AvSPrint format specification has the follwoing form
32 ',' - Place commas in numberss
33 '0' - Prefix for width with zeros
38 '*' - Get width from a UINTN argumnet from the argument list
39 Decimal number that represents width of print
42 'X' - argument is a UINTN hex number, prefix '0'
43 'x' - argument is a hex number
44 'd' - argument is a decimal number
45 'a' - argument is an ascii string
46 'S', 's' - argument is an Unicode string
47 'g' - argument is a pointer to an EFI_GUID
48 't' - argument is a pointer to an EFI_TIME structure
49 'c' - argument is an ascii character
50 'r' - argument is EFI_STATUS
66 IN OUT VA_LIST
*Marker
106 IN EFI_STATUS Status
,
116 IN CONST CHAR8
*Format
,
123 ASPrint function to process format and place the results in Buffer.
127 Buffer - Ascii buffer to print the results of the parsing of Format into.
129 BufferSize - Maximum number of characters to put into buffer. Zero means no
132 Format - Ascii format string see file header for more details.
134 ... - Vararg list consumed by processing Format.
138 Number of characters printed.
145 VA_START(Marker
, Format
);
146 Return
= AvSPrint(Buffer
, BufferSize
, Format
, Marker
);
155 OUT CHAR8
*StartOfBuffer
,
157 IN CONST CHAR8
*FormatString
,
164 AvSPrint function to process format and place the results in Buffer. Since a
165 VA_LIST is used this rountine allows the nesting of Vararg routines. Thus
166 this is the main print working routine
170 StartOfBuffer - Ascii buffer to print the results of the parsing of Format into.
172 BufferSize - Maximum number of characters to put into buffer. Zero means
175 FormatString - Ascii format string see file header for more details.
177 Marker - Vararg list consumed by processing Format.
181 Number of characters printed.
185 CHAR8 TempBuffer
[CHARACTER_NUMBER_FOR_VALUE
];
199 // Process the format string. Stop if Buffer is over run.
201 Buffer
= StartOfBuffer
;
202 Format
= (CHAR8
*) FormatString
;
203 BufferLeft
= BufferSize
;
204 for (Index
= 0; (*Format
!= '\0') && (Index
< BufferSize
- 1); Format
++) {
205 if (*Format
!= '%') {
206 if ((*Format
== '\n') && (Index
< BufferSize
- 2)) {
208 // If carage return add line feed
210 Buffer
[Index
++] = '\r';
211 BufferLeft
-= sizeof (CHAR8
);
214 Buffer
[Index
++] = *Format
;
215 BufferLeft
-= sizeof (CHAR8
);
219 // Now it's time to parse what follows after %
221 Format
= GetFlagsAndWidth (Format
, &Flags
, &Width
, &Marker
);
224 Flags
|= PREFIX_ZERO
;
225 Width
= sizeof (UINT64
) * 2;
228 // break skiped on purpose
231 if ((Flags
& LONG_TYPE
) == LONG_TYPE
) {
232 Value
= VA_ARG (Marker
, UINT64
);
234 Value
= VA_ARG (Marker
, UINTN
);
237 ValueTomHexStr (TempBuffer
, Value
, Flags
, Width
);
238 AsciiStr
= TempBuffer
;
240 for (; (*AsciiStr
!= '\0') && (Index
< BufferSize
- 1); AsciiStr
++) {
241 Buffer
[Index
++] = *AsciiStr
;
246 if ((Flags
& LONG_TYPE
) == LONG_TYPE
) {
247 Value
= VA_ARG (Marker
, UINT64
);
249 Value
= (UINTN
) VA_ARG (Marker
, UINTN
);
252 ValueToString (TempBuffer
, Value
, Flags
, Width
);
253 AsciiStr
= TempBuffer
;
255 for (; (*AsciiStr
!= '\0') && (Index
< BufferSize
- 1); AsciiStr
++) {
256 Buffer
[Index
++] = *AsciiStr
;
262 UnicodeStr
= (CHAR16
*) VA_ARG (Marker
, CHAR8
*);
263 if (UnicodeStr
== NULL
) {
264 UnicodeStr
= L
"<null string>";
267 for (Count
= 0; (*UnicodeStr
!= '\0') && (Index
< BufferSize
- 1); UnicodeStr
++, Count
++) {
268 Buffer
[Index
++] = (CHAR8
) *UnicodeStr
;
271 // Add padding if needed
273 for (; (Count
< Width
) && (Index
< BufferSize
- 1); Count
++) {
274 Buffer
[Index
++] = ' ';
280 AsciiStr
= (CHAR8
*) VA_ARG (Marker
, CHAR8
*);
281 if (AsciiStr
== NULL
) {
282 AsciiStr
= "<null string>";
285 for (Count
= 0; (*AsciiStr
!= '\0') && (Index
< BufferSize
- 1); AsciiStr
++, Count
++) {
286 Buffer
[Index
++] = *AsciiStr
;
289 // Add padding if needed
291 for (; (Count
< Width
) && (Index
< BufferSize
- 1); Count
++) {
292 Buffer
[Index
++] = ' ';
297 Buffer
[Index
++] = (CHAR8
) VA_ARG (Marker
, UINTN
);
301 TmpGUID
= VA_ARG (Marker
, EFI_GUID
*);
302 if (TmpGUID
!= NULL
) {
303 Index
+= GuidToString (
312 Index
+= TimeToString (
313 VA_ARG (Marker
, EFI_TIME
*),
320 Index
+= EfiStatusToString (
321 VA_ARG (Marker
, EFI_STATUS
),
328 Buffer
[Index
++] = *Format
;
333 // if the type is unknown print it to the screen
335 Buffer
[Index
++] = *Format
;
338 BufferLeft
= BufferSize
- Index
;
342 Buffer
[Index
++] = '\0';
344 return &Buffer
[Index
] - StartOfBuffer
;
355 IN OUT VA_LIST
*Marker
361 AvSPrint worker function that parses flag and width information from the
362 Format string and returns the next index into the Format string that needs
363 to be parsed. See file headed for details of Flag and Width.
367 Format - Current location in the AvSPrint format string.
369 Flags - Returns flags
371 Width - Returns width of element
373 Marker - Vararg list that may be paritally consumed and returned.
377 Pointer indexed into the Format string for all the information parsed
387 for (Done
= FALSE
; !Done
; ) {
392 case '-': *Flags
|= LEFT_JUSTIFY
; break;
393 case '+': *Flags
|= PREFIX_SIGN
; break;
394 case ' ': *Flags
|= PREFIX_BLANK
; break;
395 case ',': *Flags
|= COMMA_TYPE
; break;
397 case 'l': *Flags
|= LONG_TYPE
; break;
400 *Width
= VA_ARG (*Marker
, UINTN
);
404 *Flags
|= PREFIX_ZERO
;
416 Count
= (Count
* 10) + *Format
- '0';
418 } while ((*Format
>= '0') && (*Format
<= '9'));
430 static CHAR8 mHexStr
[] = { '0','1','2','3','4','5','6','7',
431 '8','9','A','B','C','D','E','F' };
436 IN OUT CHAR8
*Buffer
,
445 AvSPrint worker function that prints a Value as a hex number in Buffer
449 Buffer - Location to place ascii hex string of Value.
451 Value - Hex value to convert to a string in Buffer.
453 Flags - Flags to use in printing Hex string, see file header for details.
455 Width - Width of hex value.
459 Number of characters printed.
463 CHAR8 TempBuffer
[CHARACTER_NUMBER_FOR_VALUE
];
470 TempStr
= TempBuffer
;
474 // Count starts at one since we will null terminate. Each iteration of the
475 // loop picks off one nibble. Oh yea TempStr ends up backwards
479 *(TempStr
++) = mHexStr
[Value
& 0x0f];
480 Value
= RShiftU64 (Value
, 4);
482 } while (Value
!= 0);
484 if (Flags
& PREFIX_ZERO
) {
486 } else if (!(Flags
& LEFT_JUSTIFY
)) {
491 for (Index
= Count
; Index
< Width
; Index
++) {
492 *(TempStr
++) = Prefix
;
496 // Reverse temp string into Buffer.
498 if (Width
> 0 && (UINTN
) (TempStr
- TempBuffer
) > Width
) {
499 TempStr
= TempBuffer
+ Width
;
502 while (TempStr
!= TempBuffer
) {
503 *(BufferPtr
++) = *(--TempStr
);
514 IN OUT CHAR8
*Buffer
,
523 AvSPrint worker function that prints a Value as a decimal number in Buffer
527 Buffer - Location to place ascii decimal number string of Value.
529 Value - Decimal value to convert to a string in Buffer.
531 Flags - Flags to use in printing decimal string, see file header for details.
533 Width - Width of hex value.
537 Number of characters printed.
541 CHAR8 TempBuffer
[CHARACTER_NUMBER_FOR_VALUE
];
551 TempStr
= TempBuffer
;
562 Value
= (INT64
)DivU64x32 ((UINT64
)Value
, 10, &Remainder
);
563 *(TempStr
++) = (CHAR8
)(Remainder
+ '0');
566 if ((Flags
& COMMA_TYPE
) == COMMA_TYPE
) {
567 if (NumberCount
% 3 == 0 && Value
!= 0) {
572 } while (Value
!= 0);
575 *(BufferPtr
++) = '-';
580 // Reverse temp string into Buffer.
582 if (Width
> 0 && (UINTN
) (TempStr
- TempBuffer
) > Width
) {
583 TempStr
= TempBuffer
+ Width
;
586 while (TempStr
!= TempBuffer
) {
587 *(BufferPtr
++) = *(--TempStr
);
605 AvSPrint worker function that prints an EFI_GUID.
609 Guid - Pointer to GUID to print.
611 Buffer - Buffe to print Guid into.
613 BufferSize - Size of Buffer.
617 Number of characters printed.
626 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
630 (UINTN
)Guid
->Data4
[0],
631 (UINTN
)Guid
->Data4
[1],
632 (UINTN
)Guid
->Data4
[2],
633 (UINTN
)Guid
->Data4
[3],
634 (UINTN
)Guid
->Data4
[4],
635 (UINTN
)Guid
->Data4
[5],
636 (UINTN
)Guid
->Data4
[6],
637 (UINTN
)Guid
->Data4
[7]
641 // ASPrint will null terminate the string. The -1 skips the null
658 AvSPrint worker function that prints EFI_TIME.
662 Time - Pointer to EFI_TIME sturcture to print.
664 Buffer - Buffer to print Time into.
666 BufferSize - Size of Buffer.
670 Number of characters printed.
679 "%02d/%02d/%04d %02d:%02d",
688 // ASPrint will null terminate the string. The -1 skips the null
696 IN EFI_STATUS Status
,
704 AvSPrint worker function that prints EFI_STATUS as a string. If string is
705 not known a hex value will be printed.
709 Status - EFI_STATUS sturcture to print.
711 Buffer - Buffer to print EFI_STATUS message string into.
713 BufferSize - Size of Buffer.
717 Number of characters printed.
724 if (Status
== EFI_SUCCESS
) {
726 } else if (Status
== EFI_LOAD_ERROR
) {
728 } else if (Status
== EFI_INVALID_PARAMETER
) {
729 Desc
= "Invalid Parameter";
730 } else if (Status
== EFI_UNSUPPORTED
) {
731 Desc
= "Unsupported";
732 } else if (Status
== EFI_BAD_BUFFER_SIZE
) {
733 Desc
= "Bad Buffer Size";
734 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
735 Desc
= "Buffer Too Small";
736 } else if (Status
== EFI_NOT_READY
) {
738 } else if (Status
== EFI_DEVICE_ERROR
) {
739 Desc
= "Device Error";
740 } else if (Status
== EFI_WRITE_PROTECTED
) {
741 Desc
= "Write Protected";
742 } else if (Status
== EFI_OUT_OF_RESOURCES
) {
743 Desc
= "Out of Resources";
744 } else if (Status
== EFI_VOLUME_CORRUPTED
) {
745 Desc
= "Volume Corrupt";
746 } else if (Status
== EFI_VOLUME_FULL
) {
747 Desc
= "Volume Full";
748 } else if (Status
== EFI_NO_MEDIA
) {
750 } else if (Status
== EFI_MEDIA_CHANGED
) {
751 Desc
= "Media changed";
752 } else if (Status
== EFI_NOT_FOUND
) {
754 } else if (Status
== EFI_ACCESS_DENIED
) {
755 Desc
= "Access Denied";
756 } else if (Status
== EFI_NO_RESPONSE
) {
757 Desc
= "No Response";
758 } else if (Status
== EFI_NO_MAPPING
) {
760 } else if (Status
== EFI_TIMEOUT
) {
762 } else if (Status
== EFI_NOT_STARTED
) {
763 Desc
= "Not started";
764 } else if (Status
== EFI_ALREADY_STARTED
) {
765 Desc
= "Already started";
766 } else if (Status
== EFI_ABORTED
) {
768 } else if (Status
== EFI_ICMP_ERROR
) {
770 } else if (Status
== EFI_TFTP_ERROR
) {
772 } else if (Status
== EFI_PROTOCOL_ERROR
) {
773 Desc
= "Protocol Error";
774 } else if (Status
== EFI_WARN_UNKNOWN_GLYPH
) {
775 Desc
= "Warning Unknown Glyph";
776 } else if (Status
== EFI_WARN_DELETE_FAILURE
) {
777 Desc
= "Warning Delete Failure";
778 } else if (Status
== EFI_WARN_WRITE_FAILURE
) {
779 Desc
= "Warning Write Failure";
780 } else if (Status
== EFI_WARN_BUFFER_TOO_SMALL
) {
781 Desc
= "Warning Buffer Too Small";
786 // If we found a match, copy the message to the user's buffer. Otherwise
787 // sprint the hex status code to their buffer.
790 Size
= ASPrint (Buffer
, BufferSize
, "%a", Desc
);
792 Size
= ASPrint (Buffer
, BufferSize
, "%X", Status
);