3 Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
4 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 VSPrint(). VSPrint() enables very
19 simple implemenation of SPrint() and Print() to support debug.
21 You can not Print more than EFI_DRIVER_LIB_MAX_PRINT_BUFFER characters at a
22 time. This makes the implementation very simple.
24 VSPrint, Print, SPrint 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
56 #include "EfiDriverLib.h"
57 #include "TianoCommon.h"
58 #include "EfiCommonLib.h"
59 #include "PrintWidth.h"
60 #include "EfiPrintLib.h"
62 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
63 #include EFI_PROTOCOL_DEFINITION (HiiFont)
65 #include EFI_PROTOCOL_DEFINITION (Hii)
73 IN OUT CHAR_W
*Buffer
,
81 IN OUT CHAR_W
*Buffer
,
93 static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors
[16] = {
94 {0x00, 0x00, 0x00, 0x00},
95 {0x98, 0x00, 0x00, 0x00},
96 {0x00, 0x98, 0x00, 0x00},
97 {0x98, 0x98, 0x00, 0x00},
98 {0x00, 0x00, 0x98, 0x00},
99 {0x98, 0x00, 0x98, 0x00},
100 {0x00, 0x98, 0x98, 0x00},
101 {0x98, 0x98, 0x98, 0x00},
102 {0x10, 0x10, 0x10, 0x00},
103 {0xff, 0x10, 0x10, 0x00},
104 {0x10, 0xff, 0x10, 0x00},
105 {0xff, 0xff, 0x10, 0x00},
106 {0x10, 0x10, 0xff, 0x00},
107 {0xf0, 0x10, 0xff, 0x00},
108 {0x10, 0xff, 0xff, 0x00},
109 {0xff, 0xff, 0xff, 0x00},
115 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
116 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
,
117 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*Sto
,
120 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Foreground
,
121 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Background
,
129 Display string worker for: Print, PrintAt, IPrint, IPrintAt
133 GraphicsOutput - Graphics output protocol interface
135 UgaDraw - UGA draw protocol interface
137 Sto - Simple text out protocol interface
139 X - X coordinate to start printing
141 Y - Y coordinate to start printing
143 Foreground - Foreground color
145 Background - Background color
149 args - Print arguments
153 Length of string printed to the console
160 CHAR16
*UnicodeWeight
;
161 UINT32 HorizontalResolution
;
162 UINT32 VerticalResolution
;
167 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
168 EFI_HII_FONT_PROTOCOL
*HiiFont
;
169 EFI_IMAGE_OUTPUT
*Blt
;
170 EFI_FONT_DISPLAY_INFO
*FontInfo
;
172 EFI_HII_PROTOCOL
*Hii
;
176 EFI_NARROW_GLYPH
*Glyph
;
177 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*LineBuffer
;
181 // For now, allocate an arbitrarily long buffer
184 Buffer
= EfiLibAllocateZeroPool (0x10000);
185 if (Buffer
== NULL
) {
189 if (GraphicsOutput
!= NULL
) {
190 HorizontalResolution
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
191 VerticalResolution
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
193 UgaDraw
->GetMode (UgaDraw
, &HorizontalResolution
, &VerticalResolution
, &ColorDepth
, &RefreshRate
);
195 ASSERT ((HorizontalResolution
!= 0) && (VerticalResolution
!=0));
197 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
200 ASSERT (GraphicsOutput
!= NULL
);
201 Status
= gBS
->LocateProtocol (&gEfiHiiFontProtocolGuid
, NULL
, (VOID
**) &HiiFont
);
202 if (EFI_ERROR (Status
)) {
207 Status
= gBS
->LocateProtocol (&gEfiHiiProtocolGuid
, NULL
, (VOID
**)&Hii
);
208 if (EFI_ERROR (Status
)) {
211 LineBufferLen
= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * HorizontalResolution
* GLYPH_HEIGHT
;
212 LineBuffer
= EfiLibAllocatePool (LineBufferLen
);
213 if (LineBuffer
== NULL
) {
214 Status
= EFI_OUT_OF_RESOURCES
;
219 VSPrint (Buffer
, 0x10000, fmt
, args
);
221 UnicodeWeight
= (CHAR16
*) Buffer
;
223 for (Index
= 0; UnicodeWeight
[Index
] != 0; Index
++) {
224 if (UnicodeWeight
[Index
] == CHAR_BACKSPACE
||
225 UnicodeWeight
[Index
] == CHAR_LINEFEED
||
226 UnicodeWeight
[Index
] == CHAR_CARRIAGE_RETURN
) {
227 UnicodeWeight
[Index
] = 0;
231 BufferLen
= EfiStrLen (Buffer
);
234 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
235 LineBufferLen
= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * HorizontalResolution
* EFI_GLYPH_HEIGHT
;
236 if (EFI_GLYPH_WIDTH
* EFI_GLYPH_HEIGHT
* sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * BufferLen
> LineBufferLen
) {
237 Status
= EFI_INVALID_PARAMETER
;
241 Blt
= (EFI_IMAGE_OUTPUT
*) EfiLibAllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT
));
243 Status
= EFI_OUT_OF_RESOURCES
;
247 Blt
->Width
= (UINT16
) (HorizontalResolution
);
248 Blt
->Height
= (UINT16
) (VerticalResolution
);
249 Blt
->Image
.Screen
= GraphicsOutput
;
251 FontInfo
= (EFI_FONT_DISPLAY_INFO
*) EfiLibAllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO
));
252 if (FontInfo
== NULL
) {
253 Status
= EFI_OUT_OF_RESOURCES
;
256 if (Foreground
!= NULL
) {
257 EfiCopyMem (&FontInfo
->ForegroundColor
, Foreground
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
260 &FontInfo
->ForegroundColor
,
261 &mEfiColors
[Sto
->Mode
->Attribute
& 0x0f],
262 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
265 if (Background
!= NULL
) {
266 EfiCopyMem (&FontInfo
->BackgroundColor
, Background
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
269 &FontInfo
->BackgroundColor
,
270 &mEfiColors
[Sto
->Mode
->Attribute
>> 4],
271 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
275 Status
= HiiFont
->StringToImage (
277 EFI_HII_IGNORE_IF_NO_GLYPH
| EFI_HII_DIRECT_TO_SCREEN
,
291 if (GLYPH_WIDTH
* GLYPH_HEIGHT
* sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * BufferLen
> LineBufferLen
) {
292 Status
= EFI_INVALID_PARAMETER
;
296 for (Index
= 0; Index
< BufferLen
; Index
++) {
297 StringIndex
= (UINT16
) Index
;
298 Status
= Hii
->GetGlyph (Hii
, UnicodeWeight
, &StringIndex
, (UINT8
**) &Glyph
, &GlyphWidth
, &GlyphStatus
);
299 if (EFI_ERROR (Status
)) {
303 if (Foreground
== NULL
|| Background
== NULL
) {
304 Status
= Hii
->GlyphToBlt (
307 mEfiColors
[Sto
->Mode
->Attribute
& 0x0f],
308 mEfiColors
[Sto
->Mode
->Attribute
>> 4],
312 &LineBuffer
[Index
* GLYPH_WIDTH
]
315 Status
= Hii
->GlyphToBlt (
323 &LineBuffer
[Index
* GLYPH_WIDTH
]
329 // Blt a character to the screen
331 if (GraphicsOutput
!= NULL
) {
332 Status
= GraphicsOutput
->Blt (
340 GLYPH_WIDTH
* BufferLen
,
342 GLYPH_WIDTH
* BufferLen
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
345 Status
= UgaDraw
->Blt (
347 (EFI_UGA_PIXEL
*) LineBuffer
,
348 EfiUgaBltBufferToVideo
,
353 GLYPH_WIDTH
* BufferLen
,
355 GLYPH_WIDTH
* BufferLen
* sizeof (EFI_UGA_PIXEL
)
362 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
363 EfiLibSafeFreePool (Blt
);
364 EfiLibSafeFreePool (FontInfo
);
366 EfiLibSafeFreePool (LineBuffer
);
368 gBS
->FreePool (Buffer
);
370 if (EFI_ERROR (Status
)) {
382 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ForeGround
, OPTIONAL
383 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BackGround
, OPTIONAL
391 Prints a formatted unicode string to the default console
395 X - X coordinate to start printing
397 Y - Y coordinate to start printing
399 ForeGround - Foreground color
401 BackGround - Background color
405 ... - Print arguments
409 Length of string printed to the console
414 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
415 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
416 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*Sto
;
419 UINTN LengthOfPrinted
;
421 Handle
= gST
->ConsoleOutHandle
;
423 GraphicsOutput
= NULL
;
425 Status
= gBS
->HandleProtocol (
427 &gEfiGraphicsOutputProtocolGuid
,
428 (VOID
**)&GraphicsOutput
431 if (EFI_ERROR (Status
) || (GraphicsOutput
== NULL
)) {
432 GraphicsOutput
= NULL
;
434 Status
= gBS
->HandleProtocol (
436 &gEfiUgaDrawProtocolGuid
,
440 if (EFI_ERROR (Status
) || (UgaDraw
== NULL
)) {
446 Status
= gBS
->HandleProtocol (
448 &gEfiSimpleTextOutProtocolGuid
,
452 if (EFI_ERROR (Status
) || (Sto
== NULL
)) {
456 VA_START (Args
, Fmt
);
457 LengthOfPrinted
= _IPrint (GraphicsOutput
, UgaDraw
, Sto
, X
, Y
, ForeGround
, BackGround
, Fmt
, Args
);
459 return LengthOfPrinted
;
467 IN CONST CHAR_W
*Format
,
474 SPrint function to process format and place the results in Buffer.
478 Buffer - Wide char buffer to print the results of the parsing of Format into.
480 BufferSize - Maximum number of characters to put into buffer. Zero means no
483 Format - Format string see file header for more details.
485 ... - Vararg list consumed by processing Format.
489 Number of characters printed.
496 VA_START (Marker
, Format
);
497 Return
= VSPrint (Buffer
, BufferSize
, Format
, Marker
);
506 OUT CHAR_W
*StartOfBuffer
,
508 IN CONST CHAR_W
*FormatString
,
515 VSPrint function to process format and place the results in Buffer. Since a
516 VA_LIST is used this rountine allows the nesting of Vararg routines. Thus
517 this is the main print working routine
521 StartOfBuffer - Unicode buffer to print the results of the parsing of Format into.
523 BufferSize - Maximum number of characters to put into buffer. Zero means
526 FormatString - Unicode format string see file header for more details.
528 Marker - Vararg list consumed by processing Format.
532 Number of characters printed.
536 CHAR16 TempBuffer
[CHARACTER_NUMBER_FOR_VALUE
];
545 UINTN NumberOfCharacters
;
552 // Process the format string. Stop if Buffer is over run.
555 Buffer
= StartOfBuffer
;
556 Format
= (CHAR_W
*) FormatString
;
557 NumberOfCharacters
= BufferSize
/ sizeof (CHAR_W
);
558 BufferLeft
= BufferSize
;
559 for (Index
= 0; (*Format
!= '\0') && (Index
< NumberOfCharacters
- 1); Format
++) {
560 if (*Format
!= '%') {
561 if ((*Format
== '\n') && (Index
< NumberOfCharacters
- 2)) {
563 // If carage return add line feed
565 Buffer
[Index
++] = '\r';
566 BufferLeft
-= sizeof (CHAR_W
);
569 Buffer
[Index
++] = *Format
;
570 BufferLeft
-= sizeof (CHAR_W
);
574 // Now it's time to parse what follows after %
578 for (Done
= FALSE
; !Done
;) {
584 Flags
|= LEFT_JUSTIFY
;
588 Flags
|= PREFIX_SIGN
;
592 Flags
|= PREFIX_BLANK
;
605 Width
= VA_ARG (Marker
, UINTN
);
609 Flags
|= PREFIX_ZERO
;
622 Count
= (Count
* 10) +*Format
- '0';
624 } while ((*Format
>= '0') && (*Format
<= '9'));
637 // Flag space, +, 0, L & l are invalid for type p.
639 Flags
&= ~(PREFIX_BLANK
| PREFIX_SIGN
| LONG_TYPE
);
640 if (sizeof (VOID
*) > 4) {
642 Value
= VA_ARG (Marker
, UINT64
);
644 Value
= VA_ARG (Marker
, UINTN
);
646 Flags
|= PREFIX_ZERO
;
648 EfiValueToHexStr (TempBuffer
, Value
, Flags
, Width
);
649 UnicodeStr
= TempBuffer
;
651 for ( ;(*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++) {
652 Buffer
[Index
++] = *UnicodeStr
;
657 Flags
|= PREFIX_ZERO
;
658 Width
= sizeof (UINT64
) * 2;
661 // break skiped on purpose
664 if ((Flags
& LONG_TYPE
) == LONG_TYPE
) {
665 Value
= VA_ARG (Marker
, UINT64
);
667 Value
= VA_ARG (Marker
, UINTN
);
670 EfiValueToHexStr (TempBuffer
, Value
, Flags
, Width
);
671 UnicodeStr
= TempBuffer
;
673 for (; (*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++) {
674 Buffer
[Index
++] = *UnicodeStr
;
679 if ((Flags
& LONG_TYPE
) == LONG_TYPE
) {
680 Value
= VA_ARG (Marker
, UINT64
);
682 Value
= (UINTN
) VA_ARG (Marker
, UINTN
);
685 EfiValueToString (TempBuffer
, Value
, Flags
, Width
);
686 UnicodeStr
= TempBuffer
;
688 for (; (*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++) {
689 Buffer
[Index
++] = *UnicodeStr
;
695 UnicodeStr
= (CHAR16
*) VA_ARG (Marker
, CHAR_W
*);
696 if (UnicodeStr
== NULL
) {
697 UnicodeStr
= L
"<null string>";
700 for (Count
= 0; (*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++, Count
++) {
701 Buffer
[Index
++] = *UnicodeStr
;
704 // Add padding if needed
706 for (; (Count
< Width
) && (Index
< NumberOfCharacters
- 1); Count
++) {
707 Buffer
[Index
++] = ' ';
713 AsciiStr
= (CHAR8
*) VA_ARG (Marker
, CHAR8
*);
714 if (AsciiStr
== NULL
) {
715 AsciiStr
= (CHAR8
*) "<null string>";
718 for (Count
= 0; (*AsciiStr
!= '\0') && (Index
< NumberOfCharacters
- 1); AsciiStr
++, Count
++) {
719 Buffer
[Index
++] = (CHAR_W
) * AsciiStr
;
722 // Add padding if needed
724 for (; (Count
< Width
) && (Index
< NumberOfCharacters
- 1); Count
++) {
725 Buffer
[Index
++] = ' ';
730 Buffer
[Index
++] = (CHAR_W
) VA_ARG (Marker
, UINTN
);
734 TmpGUID
= VA_ARG (Marker
, EFI_GUID
*);
735 if (TmpGUID
!= NULL
) {
736 Index
+= GuidToString (
745 Index
+= TimeToString (
746 VA_ARG (Marker
, EFI_TIME
*),
753 Index
+= EfiStatusToString (
754 VA_ARG (Marker
, EFI_STATUS
),
761 Buffer
[Index
++] = *Format
;
766 // if the type is unknown print it to the screen
768 Buffer
[Index
++] = *Format
;
771 BufferLeft
= BufferSize
- Index
* sizeof (CHAR_W
);
775 Buffer
[Index
++] = '\0';
777 return &Buffer
[Index
] - StartOfBuffer
;
791 VSPrint worker function that prints an EFI_GUID.
795 Guid - Pointer to GUID to print.
797 Buffer - Buffe to print Guid into.
799 BufferSize - Size of Buffer.
803 Number of characters printed.
812 STRING_W ("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"),
816 (UINTN
)Guid
->Data4
[0],
817 (UINTN
)Guid
->Data4
[1],
818 (UINTN
)Guid
->Data4
[2],
819 (UINTN
)Guid
->Data4
[3],
820 (UINTN
)Guid
->Data4
[4],
821 (UINTN
)Guid
->Data4
[5],
822 (UINTN
)Guid
->Data4
[6],
823 (UINTN
)Guid
->Data4
[7]
827 // SPrint will null terminate the string. The -1 skips the null
844 VSPrint worker function that prints EFI_TIME.
848 Time - Pointer to EFI_TIME sturcture to print.
850 Buffer - Buffer to print Time into.
852 BufferSize - Size of Buffer.
856 Number of characters printed.
865 STRING_W ("%02d/%02d/%04d %02d:%02d"),
874 // SPrint will null terminate the string. The -1 skips the null
882 IN EFI_STATUS Status
,
890 VSPrint worker function that prints EFI_STATUS as a string. If string is
891 not known a hex value will be printed.
895 Status - EFI_STATUS sturcture to print.
897 Buffer - Buffer to print EFI_STATUS message string into.
899 BufferSize - Size of Buffer.
903 Number of characters printed.
913 // Can't use global Status String Array as UINTN is not constant for EBC
915 if (Status
== EFI_SUCCESS
) { Desc
= (CHAR8
*) "Success"; } else
916 if (Status
== EFI_LOAD_ERROR
) { Desc
= (CHAR8
*) "Load Error"; } else
917 if (Status
== EFI_INVALID_PARAMETER
) { Desc
= (CHAR8
*) "Invalid Parameter"; } else
918 if (Status
== EFI_UNSUPPORTED
) { Desc
= (CHAR8
*) "Unsupported"; } else
919 if (Status
== EFI_BAD_BUFFER_SIZE
) { Desc
= (CHAR8
*) "Bad Buffer Size"; } else
920 if (Status
== EFI_BUFFER_TOO_SMALL
) { Desc
= (CHAR8
*) "Buffer Too Small"; } else
921 if (Status
== EFI_NOT_READY
) { Desc
= (CHAR8
*) "Not Ready"; } else
922 if (Status
== EFI_DEVICE_ERROR
) { Desc
= (CHAR8
*) "Device Error"; } else
923 if (Status
== EFI_WRITE_PROTECTED
) { Desc
= (CHAR8
*) "Write Protected"; } else
924 if (Status
== EFI_OUT_OF_RESOURCES
) { Desc
= (CHAR8
*) "Out of Resources"; } else
925 if (Status
== EFI_VOLUME_CORRUPTED
) { Desc
= (CHAR8
*) "Volume Corrupt"; } else
926 if (Status
== EFI_VOLUME_FULL
) { Desc
= (CHAR8
*) "Volume Full"; } else
927 if (Status
== EFI_NO_MEDIA
) { Desc
= (CHAR8
*) "No Media"; } else
928 if (Status
== EFI_MEDIA_CHANGED
) { Desc
= (CHAR8
*) "Media changed"; } else
929 if (Status
== EFI_NOT_FOUND
) { Desc
= (CHAR8
*) "Not Found"; } else
930 if (Status
== EFI_ACCESS_DENIED
) { Desc
= (CHAR8
*) "Access Denied"; } else
931 if (Status
== EFI_NO_RESPONSE
) { Desc
= (CHAR8
*) "No Response"; } else
932 if (Status
== EFI_NO_MAPPING
) { Desc
= (CHAR8
*) "No mapping"; } else
933 if (Status
== EFI_TIMEOUT
) { Desc
= (CHAR8
*) "Time out"; } else
934 if (Status
== EFI_NOT_STARTED
) { Desc
= (CHAR8
*) "Not started"; } else
935 if (Status
== EFI_ALREADY_STARTED
) { Desc
= (CHAR8
*) "Already started"; } else
936 if (Status
== EFI_ABORTED
) { Desc
= (CHAR8
*) "Aborted"; } else
937 if (Status
== EFI_ICMP_ERROR
) { Desc
= (CHAR8
*) "ICMP Error"; } else
938 if (Status
== EFI_TFTP_ERROR
) { Desc
= (CHAR8
*) "TFTP Error"; } else
939 if (Status
== EFI_PROTOCOL_ERROR
) { Desc
= (CHAR8
*) "Protocol Error"; } else
940 if (Status
== EFI_WARN_UNKNOWN_GLYPH
) { Desc
= (CHAR8
*) "Warning Unknown Glyph"; } else
941 if (Status
== EFI_WARN_DELETE_FAILURE
) { Desc
= (CHAR8
*) "Warning Delete Failure"; } else
942 if (Status
== EFI_WARN_WRITE_FAILURE
) { Desc
= (CHAR8
*) "Warning Write Failure"; } else
943 if (Status
== EFI_WARN_BUFFER_TOO_SMALL
) { Desc
= (CHAR8
*) "Warning Buffer Too Small"; }
946 // If we found a match, copy the message to the user's buffer. Otherwise
947 // sprint the hex status code to their buffer.
950 Size
= SPrint (Buffer
, BufferSize
, STRING_W ("%a"), Desc
);
952 Size
= SPrint (Buffer
, BufferSize
, STRING_W ("%X"), Status
);