3 Copyright (c) 2004 - 2010, 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
;
420 VA_START (Args
, Fmt
);
422 Handle
= gST
->ConsoleOutHandle
;
424 GraphicsOutput
= NULL
;
426 Status
= gBS
->HandleProtocol (
428 &gEfiGraphicsOutputProtocolGuid
,
429 (VOID
**)&GraphicsOutput
432 if (EFI_ERROR (Status
) || (GraphicsOutput
== NULL
)) {
433 GraphicsOutput
= NULL
;
435 Status
= gBS
->HandleProtocol (
437 &gEfiUgaDrawProtocolGuid
,
441 if (EFI_ERROR (Status
) || (UgaDraw
== NULL
)) {
447 Status
= gBS
->HandleProtocol (
449 &gEfiSimpleTextOutProtocolGuid
,
453 if (EFI_ERROR (Status
) || (Sto
== NULL
)) {
457 return _IPrint (GraphicsOutput
, UgaDraw
, Sto
, X
, Y
, ForeGround
, BackGround
, Fmt
, Args
);
465 IN CONST CHAR_W
*Format
,
472 SPrint function to process format and place the results in Buffer.
476 Buffer - Wide char buffer to print the results of the parsing of Format into.
478 BufferSize - Maximum number of characters to put into buffer. Zero means no
481 Format - Format string see file header for more details.
483 ... - Vararg list consumed by processing Format.
487 Number of characters printed.
494 VA_START (Marker
, Format
);
495 Return
= VSPrint (Buffer
, BufferSize
, Format
, Marker
);
504 OUT CHAR_W
*StartOfBuffer
,
506 IN CONST CHAR_W
*FormatString
,
513 VSPrint function to process format and place the results in Buffer. Since a
514 VA_LIST is used this rountine allows the nesting of Vararg routines. Thus
515 this is the main print working routine
519 StartOfBuffer - Unicode buffer to print the results of the parsing of Format into.
521 BufferSize - Maximum number of characters to put into buffer. Zero means
524 FormatString - Unicode format string see file header for more details.
526 Marker - Vararg list consumed by processing Format.
530 Number of characters printed.
534 CHAR16 TempBuffer
[CHARACTER_NUMBER_FOR_VALUE
];
543 UINTN NumberOfCharacters
;
550 // Process the format string. Stop if Buffer is over run.
553 Buffer
= StartOfBuffer
;
554 Format
= (CHAR_W
*) FormatString
;
555 NumberOfCharacters
= BufferSize
/ sizeof (CHAR_W
);
556 BufferLeft
= BufferSize
;
557 for (Index
= 0; (*Format
!= '\0') && (Index
< NumberOfCharacters
- 1); Format
++) {
558 if (*Format
!= '%') {
559 if ((*Format
== '\n') && (Index
< NumberOfCharacters
- 2)) {
561 // If carage return add line feed
563 Buffer
[Index
++] = '\r';
564 BufferLeft
-= sizeof (CHAR_W
);
567 Buffer
[Index
++] = *Format
;
568 BufferLeft
-= sizeof (CHAR_W
);
572 // Now it's time to parse what follows after %
576 for (Done
= FALSE
; !Done
;) {
582 Flags
|= LEFT_JUSTIFY
;
586 Flags
|= PREFIX_SIGN
;
590 Flags
|= PREFIX_BLANK
;
603 Width
= VA_ARG (Marker
, UINTN
);
607 Flags
|= PREFIX_ZERO
;
620 Count
= (Count
* 10) +*Format
- '0';
622 } while ((*Format
>= '0') && (*Format
<= '9'));
635 // Flag space, +, 0, L & l are invalid for type p.
637 Flags
&= ~(PREFIX_BLANK
| PREFIX_SIGN
| LONG_TYPE
);
638 if (sizeof (VOID
*) > 4) {
640 Value
= VA_ARG (Marker
, UINT64
);
642 Value
= VA_ARG (Marker
, UINTN
);
644 Flags
|= PREFIX_ZERO
;
646 EfiValueToHexStr (TempBuffer
, Value
, Flags
, Width
);
647 UnicodeStr
= TempBuffer
;
649 for ( ;(*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++) {
650 Buffer
[Index
++] = *UnicodeStr
;
655 Flags
|= PREFIX_ZERO
;
656 Width
= sizeof (UINT64
) * 2;
659 // break skiped on purpose
662 if ((Flags
& LONG_TYPE
) == LONG_TYPE
) {
663 Value
= VA_ARG (Marker
, UINT64
);
665 Value
= VA_ARG (Marker
, UINTN
);
668 EfiValueToHexStr (TempBuffer
, Value
, Flags
, Width
);
669 UnicodeStr
= TempBuffer
;
671 for (; (*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++) {
672 Buffer
[Index
++] = *UnicodeStr
;
677 if ((Flags
& LONG_TYPE
) == LONG_TYPE
) {
678 Value
= VA_ARG (Marker
, UINT64
);
680 Value
= (UINTN
) VA_ARG (Marker
, UINTN
);
683 EfiValueToString (TempBuffer
, Value
, Flags
, Width
);
684 UnicodeStr
= TempBuffer
;
686 for (; (*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++) {
687 Buffer
[Index
++] = *UnicodeStr
;
693 UnicodeStr
= (CHAR16
*) VA_ARG (Marker
, CHAR_W
*);
694 if (UnicodeStr
== NULL
) {
695 UnicodeStr
= L
"<null string>";
698 for (Count
= 0; (*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++, Count
++) {
699 Buffer
[Index
++] = *UnicodeStr
;
702 // Add padding if needed
704 for (; (Count
< Width
) && (Index
< NumberOfCharacters
- 1); Count
++) {
705 Buffer
[Index
++] = ' ';
711 AsciiStr
= (CHAR8
*) VA_ARG (Marker
, CHAR8
*);
712 if (AsciiStr
== NULL
) {
713 AsciiStr
= (CHAR8
*) "<null string>";
716 for (Count
= 0; (*AsciiStr
!= '\0') && (Index
< NumberOfCharacters
- 1); AsciiStr
++, Count
++) {
717 Buffer
[Index
++] = (CHAR_W
) * AsciiStr
;
720 // Add padding if needed
722 for (; (Count
< Width
) && (Index
< NumberOfCharacters
- 1); Count
++) {
723 Buffer
[Index
++] = ' ';
728 Buffer
[Index
++] = (CHAR_W
) VA_ARG (Marker
, UINTN
);
732 TmpGUID
= VA_ARG (Marker
, EFI_GUID
*);
733 if (TmpGUID
!= NULL
) {
734 Index
+= GuidToString (
743 Index
+= TimeToString (
744 VA_ARG (Marker
, EFI_TIME
*),
751 Index
+= EfiStatusToString (
752 VA_ARG (Marker
, EFI_STATUS
),
759 Buffer
[Index
++] = *Format
;
764 // if the type is unknown print it to the screen
766 Buffer
[Index
++] = *Format
;
769 BufferLeft
= BufferSize
- Index
* sizeof (CHAR_W
);
773 Buffer
[Index
++] = '\0';
775 return &Buffer
[Index
] - StartOfBuffer
;
789 VSPrint worker function that prints an EFI_GUID.
793 Guid - Pointer to GUID to print.
795 Buffer - Buffe to print Guid into.
797 BufferSize - Size of Buffer.
801 Number of characters printed.
810 STRING_W ("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"),
814 (UINTN
)Guid
->Data4
[0],
815 (UINTN
)Guid
->Data4
[1],
816 (UINTN
)Guid
->Data4
[2],
817 (UINTN
)Guid
->Data4
[3],
818 (UINTN
)Guid
->Data4
[4],
819 (UINTN
)Guid
->Data4
[5],
820 (UINTN
)Guid
->Data4
[6],
821 (UINTN
)Guid
->Data4
[7]
825 // SPrint will null terminate the string. The -1 skips the null
842 VSPrint worker function that prints EFI_TIME.
846 Time - Pointer to EFI_TIME sturcture to print.
848 Buffer - Buffer to print Time into.
850 BufferSize - Size of Buffer.
854 Number of characters printed.
863 STRING_W ("%02d/%02d/%04d %02d:%02d"),
872 // SPrint will null terminate the string. The -1 skips the null
880 IN EFI_STATUS Status
,
888 VSPrint worker function that prints EFI_STATUS as a string. If string is
889 not known a hex value will be printed.
893 Status - EFI_STATUS sturcture to print.
895 Buffer - Buffer to print EFI_STATUS message string into.
897 BufferSize - Size of Buffer.
901 Number of characters printed.
911 // Can't use global Status String Array as UINTN is not constant for EBC
913 if (Status
== EFI_SUCCESS
) { Desc
= (CHAR8
*) "Success"; } else
914 if (Status
== EFI_LOAD_ERROR
) { Desc
= (CHAR8
*) "Load Error"; } else
915 if (Status
== EFI_INVALID_PARAMETER
) { Desc
= (CHAR8
*) "Invalid Parameter"; } else
916 if (Status
== EFI_UNSUPPORTED
) { Desc
= (CHAR8
*) "Unsupported"; } else
917 if (Status
== EFI_BAD_BUFFER_SIZE
) { Desc
= (CHAR8
*) "Bad Buffer Size"; } else
918 if (Status
== EFI_BUFFER_TOO_SMALL
) { Desc
= (CHAR8
*) "Buffer Too Small"; } else
919 if (Status
== EFI_NOT_READY
) { Desc
= (CHAR8
*) "Not Ready"; } else
920 if (Status
== EFI_DEVICE_ERROR
) { Desc
= (CHAR8
*) "Device Error"; } else
921 if (Status
== EFI_WRITE_PROTECTED
) { Desc
= (CHAR8
*) "Write Protected"; } else
922 if (Status
== EFI_OUT_OF_RESOURCES
) { Desc
= (CHAR8
*) "Out of Resources"; } else
923 if (Status
== EFI_VOLUME_CORRUPTED
) { Desc
= (CHAR8
*) "Volume Corrupt"; } else
924 if (Status
== EFI_VOLUME_FULL
) { Desc
= (CHAR8
*) "Volume Full"; } else
925 if (Status
== EFI_NO_MEDIA
) { Desc
= (CHAR8
*) "No Media"; } else
926 if (Status
== EFI_MEDIA_CHANGED
) { Desc
= (CHAR8
*) "Media changed"; } else
927 if (Status
== EFI_NOT_FOUND
) { Desc
= (CHAR8
*) "Not Found"; } else
928 if (Status
== EFI_ACCESS_DENIED
) { Desc
= (CHAR8
*) "Access Denied"; } else
929 if (Status
== EFI_NO_RESPONSE
) { Desc
= (CHAR8
*) "No Response"; } else
930 if (Status
== EFI_NO_MAPPING
) { Desc
= (CHAR8
*) "No mapping"; } else
931 if (Status
== EFI_TIMEOUT
) { Desc
= (CHAR8
*) "Time out"; } else
932 if (Status
== EFI_NOT_STARTED
) { Desc
= (CHAR8
*) "Not started"; } else
933 if (Status
== EFI_ALREADY_STARTED
) { Desc
= (CHAR8
*) "Already started"; } else
934 if (Status
== EFI_ABORTED
) { Desc
= (CHAR8
*) "Aborted"; } else
935 if (Status
== EFI_ICMP_ERROR
) { Desc
= (CHAR8
*) "ICMP Error"; } else
936 if (Status
== EFI_TFTP_ERROR
) { Desc
= (CHAR8
*) "TFTP Error"; } else
937 if (Status
== EFI_PROTOCOL_ERROR
) { Desc
= (CHAR8
*) "Protocol Error"; } else
938 if (Status
== EFI_WARN_UNKNOWN_GLYPH
) { Desc
= (CHAR8
*) "Warning Unknown Glyph"; } else
939 if (Status
== EFI_WARN_DELETE_FAILURE
) { Desc
= (CHAR8
*) "Warning Delete Failure"; } else
940 if (Status
== EFI_WARN_WRITE_FAILURE
) { Desc
= (CHAR8
*) "Warning Write Failure"; } else
941 if (Status
== EFI_WARN_BUFFER_TOO_SMALL
) { Desc
= (CHAR8
*) "Warning Buffer Too Small"; }
944 // If we found a match, copy the message to the user's buffer. Otherwise
945 // sprint the hex status code to their buffer.
948 Size
= SPrint (Buffer
, BufferSize
, STRING_W ("%a"), Desc
);
950 Size
= SPrint (Buffer
, BufferSize
, STRING_W ("%X"), Status
);