3 Copyright (c) 2004 - 2007, 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 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)
74 IN OUT VA_LIST
*Marker
81 IN OUT CHAR_W
*Buffer
,
89 IN OUT CHAR_W
*Buffer
,
101 static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors
[16] = {
102 0x00, 0x00, 0x00, 0x00,
103 0x98, 0x00, 0x00, 0x00,
104 0x00, 0x98, 0x00, 0x00,
105 0x98, 0x98, 0x00, 0x00,
106 0x00, 0x00, 0x98, 0x00,
107 0x98, 0x00, 0x98, 0x00,
108 0x00, 0x98, 0x98, 0x00,
109 0x98, 0x98, 0x98, 0x00,
110 0x10, 0x10, 0x10, 0x00,
111 0xff, 0x10, 0x10, 0x00,
112 0x10, 0xff, 0x10, 0x00,
113 0xff, 0xff, 0x10, 0x00,
114 0x10, 0x10, 0xff, 0x00,
115 0xf0, 0x10, 0xff, 0x00,
116 0x10, 0xff, 0xff, 0x00,
117 0xff, 0xff, 0xff, 0x00,
123 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
124 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
,
125 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*Sto
,
128 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Foreground
,
129 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Background
,
137 Display string worker for: Print, PrintAt, IPrint, IPrintAt
141 GraphicsOutput - Graphics output protocol interface
143 UgaDraw - UGA draw protocol interface
145 Sto - Simple text out protocol interface
147 X - X coordinate to start printing
149 Y - Y coordinate to start printing
151 Foreground - Foreground color
153 Background - Background color
157 args - Print arguments
161 EFI_SUCCESS - success
162 EFI_OUT_OF_RESOURCES - out of resources
169 CHAR16
*UnicodeWeight
;
170 UINT32 HorizontalResolution
;
171 UINT32 VerticalResolution
;
176 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
177 EFI_HII_FONT_PROTOCOL
*HiiFont
;
178 EFI_IMAGE_OUTPUT
*Blt
;
179 EFI_FONT_DISPLAY_INFO
*FontInfo
;
181 EFI_HII_PROTOCOL
*Hii
;
185 EFI_NARROW_GLYPH
*Glyph
;
186 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*LineBuffer
;
190 // For now, allocate an arbitrarily long buffer
192 Buffer
= EfiLibAllocateZeroPool (0x10000);
193 if (Buffer
== NULL
) {
194 return EFI_OUT_OF_RESOURCES
;
197 if (GraphicsOutput
!= NULL
) {
198 HorizontalResolution
= GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
199 VerticalResolution
= GraphicsOutput
->Mode
->Info
->VerticalResolution
;
201 UgaDraw
->GetMode (UgaDraw
, &HorizontalResolution
, &VerticalResolution
, &ColorDepth
, &RefreshRate
);
203 ASSERT ((HorizontalResolution
!= 0) && (VerticalResolution
!=0));
205 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
208 ASSERT (GraphicsOutput
!= NULL
);
209 Status
= gBS
->LocateProtocol (&gEfiHiiFontProtocolGuid
, NULL
, (VOID
**) &HiiFont
);
210 if (EFI_ERROR (Status
)) {
215 Status
= gBS
->LocateProtocol (&gEfiHiiProtocolGuid
, NULL
, (VOID
**)&Hii
);
216 if (EFI_ERROR (Status
)) {
219 LineBufferLen
= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * HorizontalResolution
* GLYPH_HEIGHT
;
220 LineBuffer
= EfiLibAllocatePool (LineBufferLen
);
221 if (LineBuffer
== NULL
) {
222 Status
= EFI_OUT_OF_RESOURCES
;
227 VSPrint (Buffer
, 0x10000, fmt
, args
);
229 UnicodeWeight
= (CHAR16
*) Buffer
;
231 for (Index
= 0; UnicodeWeight
[Index
] != 0; Index
++) {
232 if (UnicodeWeight
[Index
] == CHAR_BACKSPACE
||
233 UnicodeWeight
[Index
] == CHAR_LINEFEED
||
234 UnicodeWeight
[Index
] == CHAR_CARRIAGE_RETURN
) {
235 UnicodeWeight
[Index
] = 0;
239 BufferLen
= EfiStrLen (Buffer
);
242 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
243 LineBufferLen
= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * HorizontalResolution
* EFI_GLYPH_HEIGHT
;
244 if (EFI_GLYPH_WIDTH
* EFI_GLYPH_HEIGHT
* sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * BufferLen
> LineBufferLen
) {
245 Status
= EFI_INVALID_PARAMETER
;
249 Blt
= (EFI_IMAGE_OUTPUT
*) EfiLibAllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT
));
251 Status
= EFI_OUT_OF_RESOURCES
;
255 Blt
->Width
= (UINT16
) (HorizontalResolution
);
256 Blt
->Height
= (UINT16
) (VerticalResolution
);
257 Blt
->Image
.Screen
= GraphicsOutput
;
259 FontInfo
= (EFI_FONT_DISPLAY_INFO
*) EfiLibAllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO
));
260 if (FontInfo
== NULL
) {
261 Status
= EFI_OUT_OF_RESOURCES
;
264 if (Foreground
!= NULL
) {
265 EfiCopyMem (&FontInfo
->ForegroundColor
, Foreground
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
268 &FontInfo
->ForegroundColor
,
269 &mEfiColors
[Sto
->Mode
->Attribute
& 0x0f],
270 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
273 if (Background
!= NULL
) {
274 EfiCopyMem (&FontInfo
->BackgroundColor
, Background
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
277 &FontInfo
->BackgroundColor
,
278 &mEfiColors
[Sto
->Mode
->Attribute
>> 4],
279 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
283 Status
= HiiFont
->StringToImage (
285 EFI_HII_IGNORE_IF_NO_GLYPH
| EFI_HII_DIRECT_TO_SCREEN
,
299 if (GLYPH_WIDTH
* GLYPH_HEIGHT
* sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * BufferLen
> LineBufferLen
) {
300 Status
= EFI_INVALID_PARAMETER
;
304 for (Index
= 0; Index
< BufferLen
; Index
++) {
305 StringIndex
= (UINT16
) Index
;
306 Status
= Hii
->GetGlyph (Hii
, UnicodeWeight
, &StringIndex
, (UINT8
**) &Glyph
, &GlyphWidth
, &GlyphStatus
);
307 if (EFI_ERROR (Status
)) {
311 if (Foreground
== NULL
|| Background
== NULL
) {
312 Status
= Hii
->GlyphToBlt (
315 mEfiColors
[Sto
->Mode
->Attribute
& 0x0f],
316 mEfiColors
[Sto
->Mode
->Attribute
>> 4],
320 &LineBuffer
[Index
* GLYPH_WIDTH
]
323 Status
= Hii
->GlyphToBlt (
331 &LineBuffer
[Index
* GLYPH_WIDTH
]
337 // Blt a character to the screen
339 if (GraphicsOutput
!= NULL
) {
340 Status
= GraphicsOutput
->Blt (
348 GLYPH_WIDTH
* BufferLen
,
350 GLYPH_WIDTH
* BufferLen
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
353 Status
= UgaDraw
->Blt (
355 (EFI_UGA_PIXEL
*) LineBuffer
,
356 EfiUgaBltBufferToVideo
,
361 GLYPH_WIDTH
* BufferLen
,
363 GLYPH_WIDTH
* BufferLen
* sizeof (EFI_UGA_PIXEL
)
370 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
371 EfiLibSafeFreePool (Blt
);
372 EfiLibSafeFreePool (FontInfo
);
374 gBS
->FreePool (LineBuffer
);
376 gBS
->FreePool (Buffer
);
385 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ForeGround
, OPTIONAL
386 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BackGround
, OPTIONAL
394 Prints a formatted unicode string to the default console
398 X - X coordinate to start printing
400 Y - Y coordinate to start printing
402 ForeGround - Foreground color
404 BackGround - Background color
408 ... - Print arguments
412 Length of string printed to the console
417 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
418 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
419 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*Sto
;
423 VA_START (Args
, Fmt
);
425 Handle
= gST
->ConsoleOutHandle
;
427 Status
= gBS
->HandleProtocol (
429 &gEfiGraphicsOutputProtocolGuid
,
430 (VOID
**)&GraphicsOutput
434 if (EFI_ERROR (Status
)) {
435 GraphicsOutput
= NULL
;
437 Status
= gBS
->HandleProtocol (
439 &gEfiUgaDrawProtocolGuid
,
443 if (EFI_ERROR (Status
)) {
448 Status
= gBS
->HandleProtocol (
450 &gEfiSimpleTextOutProtocolGuid
,
454 if (EFI_ERROR (Status
)) {
458 return _IPrint (GraphicsOutput
, UgaDraw
, Sto
, X
, Y
, ForeGround
, BackGround
, Fmt
, Args
);
466 IN CONST CHAR_W
*Format
,
473 SPrint function to process format and place the results in Buffer.
477 Buffer - Wide char buffer to print the results of the parsing of Format into.
479 BufferSize - Maximum number of characters to put into buffer. Zero means no
482 Format - Format string see file header for more details.
484 ... - Vararg list consumed by processing Format.
488 Number of characters printed.
495 VA_START (Marker
, Format
);
496 Return
= VSPrint (Buffer
, BufferSize
, Format
, Marker
);
505 OUT CHAR_W
*StartOfBuffer
,
507 IN CONST CHAR_W
*FormatString
,
514 VSPrint function to process format and place the results in Buffer. Since a
515 VA_LIST is used this rountine allows the nesting of Vararg routines. Thus
516 this is the main print working routine
520 StartOfBuffer - Unicode buffer to print the results of the parsing of Format into.
522 BufferSize - Maximum number of characters to put into buffer. Zero means
525 FormatString - Unicode format string see file header for more details.
527 Marker - Vararg list consumed by processing Format.
531 Number of characters printed.
535 CHAR16 TempBuffer
[CHARACTER_NUMBER_FOR_VALUE
];
544 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 %
574 Format
= GetFlagsAndWidth (Format
, &Flags
, &Width
, &Marker
);
577 Flags
|= PREFIX_ZERO
;
578 Width
= sizeof (UINT64
) * 2;
581 // break skiped on purpose
584 if ((Flags
& LONG_TYPE
) == LONG_TYPE
) {
585 Value
= VA_ARG (Marker
, UINT64
);
587 Value
= VA_ARG (Marker
, UINTN
);
590 EfiValueToHexStr (TempBuffer
, Value
, Flags
, Width
);
591 UnicodeStr
= TempBuffer
;
593 for (; (*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++) {
594 Buffer
[Index
++] = *UnicodeStr
;
599 if ((Flags
& LONG_TYPE
) == LONG_TYPE
) {
600 Value
= VA_ARG (Marker
, UINT64
);
602 Value
= (UINTN
) VA_ARG (Marker
, UINTN
);
605 EfiValueToString (TempBuffer
, Value
, Flags
, Width
);
606 UnicodeStr
= TempBuffer
;
608 for (; (*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++) {
609 Buffer
[Index
++] = *UnicodeStr
;
615 UnicodeStr
= (CHAR16
*) VA_ARG (Marker
, CHAR_W
*);
616 if (UnicodeStr
== NULL
) {
617 UnicodeStr
= L
"<null string>";
620 for (Count
= 0; (*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++, Count
++) {
621 Buffer
[Index
++] = *UnicodeStr
;
624 // Add padding if needed
626 for (; (Count
< Width
) && (Index
< NumberOfCharacters
- 1); Count
++) {
627 Buffer
[Index
++] = ' ';
633 AsciiStr
= (CHAR8
*) VA_ARG (Marker
, CHAR8
*);
634 if (AsciiStr
== NULL
) {
635 AsciiStr
= "<null string>";
638 for (Count
= 0; (*AsciiStr
!= '\0') && (Index
< NumberOfCharacters
- 1); AsciiStr
++, Count
++) {
639 Buffer
[Index
++] = (CHAR_W
) * AsciiStr
;
642 // Add padding if needed
644 for (; (Count
< Width
) && (Index
< NumberOfCharacters
- 1); Count
++) {
645 Buffer
[Index
++] = ' ';
650 Buffer
[Index
++] = (CHAR_W
) VA_ARG (Marker
, UINTN
);
654 TmpGUID
= VA_ARG (Marker
, EFI_GUID
*);
655 if (TmpGUID
!= NULL
) {
656 Index
+= GuidToString (
665 Index
+= TimeToString (
666 VA_ARG (Marker
, EFI_TIME
*),
673 Index
+= EfiStatusToString (
674 VA_ARG (Marker
, EFI_STATUS
),
681 Buffer
[Index
++] = *Format
;
686 // if the type is unknown print it to the screen
688 Buffer
[Index
++] = *Format
;
691 BufferLeft
= BufferSize
- Index
* sizeof (CHAR_W
);
695 Buffer
[Index
++] = '\0';
697 return &Buffer
[Index
] - StartOfBuffer
;
706 IN OUT VA_LIST
*Marker
712 VSPrint worker function that parses flag and width information from the
713 Format string and returns the next index into the Format string that needs
714 to be parsed. See file headed for details of Flag and Width.
718 Format - Current location in the VSPrint format string.
720 Flags - Returns flags
722 Width - Returns width of element
724 Marker - Vararg list that may be paritally consumed and returned.
728 Pointer indexed into the Format string for all the information parsed
738 for (Done
= FALSE
; !Done
;) {
744 *Flags
|= LEFT_JUSTIFY
;
748 *Flags
|= PREFIX_SIGN
;
752 *Flags
|= PREFIX_BLANK
;
756 *Flags
|= COMMA_TYPE
;
765 *Width
= VA_ARG (*Marker
, UINTN
);
769 *Flags
|= PREFIX_ZERO
;
782 Count
= (Count
* 10) +*Format
- '0';
784 } while ((*Format
>= '0') && (*Format
<= '9'));
808 VSPrint worker function that prints an EFI_GUID.
812 Guid - Pointer to GUID to print.
814 Buffer - Buffe to print Guid into.
816 BufferSize - Size of Buffer.
820 Number of characters printed.
829 STRING_W ("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"),
833 (UINTN
)Guid
->Data4
[0],
834 (UINTN
)Guid
->Data4
[1],
835 (UINTN
)Guid
->Data4
[2],
836 (UINTN
)Guid
->Data4
[3],
837 (UINTN
)Guid
->Data4
[4],
838 (UINTN
)Guid
->Data4
[5],
839 (UINTN
)Guid
->Data4
[6],
840 (UINTN
)Guid
->Data4
[7]
844 // SPrint will null terminate the string. The -1 skips the null
861 VSPrint worker function that prints EFI_TIME.
865 Time - Pointer to EFI_TIME sturcture to print.
867 Buffer - Buffer to print Time into.
869 BufferSize - Size of Buffer.
873 Number of characters printed.
882 STRING_W ("%02d/%02d/%04d %02d:%02d"),
891 // SPrint will null terminate the string. The -1 skips the null
899 IN EFI_STATUS Status
,
907 VSPrint worker function that prints EFI_STATUS as a string. If string is
908 not known a hex value will be printed.
912 Status - EFI_STATUS sturcture to print.
914 Buffer - Buffer to print EFI_STATUS message string into.
916 BufferSize - Size of Buffer.
920 Number of characters printed.
930 // Can't use global Status String Array as UINTN is not constant for EBC
932 if (Status
== EFI_SUCCESS
) { Desc
= "Success"; } else
933 if (Status
== EFI_LOAD_ERROR
) { Desc
= "Load Error"; } else
934 if (Status
== EFI_INVALID_PARAMETER
) { Desc
= "Invalid Parameter"; } else
935 if (Status
== EFI_UNSUPPORTED
) { Desc
= "Unsupported"; } else
936 if (Status
== EFI_BAD_BUFFER_SIZE
) { Desc
= "Bad Buffer Size"; } else
937 if (Status
== EFI_BUFFER_TOO_SMALL
) { Desc
= "Buffer Too Small"; } else
938 if (Status
== EFI_NOT_READY
) { Desc
= "Not Ready"; } else
939 if (Status
== EFI_DEVICE_ERROR
) { Desc
= "Device Error"; } else
940 if (Status
== EFI_WRITE_PROTECTED
) { Desc
= "Write Protected"; } else
941 if (Status
== EFI_OUT_OF_RESOURCES
) { Desc
= "Out of Resources"; } else
942 if (Status
== EFI_VOLUME_CORRUPTED
) { Desc
= "Volume Corrupt"; } else
943 if (Status
== EFI_VOLUME_FULL
) { Desc
= "Volume Full"; } else
944 if (Status
== EFI_NO_MEDIA
) { Desc
= "No Media"; } else
945 if (Status
== EFI_MEDIA_CHANGED
) { Desc
= "Media changed"; } else
946 if (Status
== EFI_NOT_FOUND
) { Desc
= "Not Found"; } else
947 if (Status
== EFI_ACCESS_DENIED
) { Desc
= "Access Denied"; } else
948 if (Status
== EFI_NO_RESPONSE
) { Desc
= "No Response"; } else
949 if (Status
== EFI_NO_MAPPING
) { Desc
= "No mapping"; } else
950 if (Status
== EFI_TIMEOUT
) { Desc
= "Time out"; } else
951 if (Status
== EFI_NOT_STARTED
) { Desc
= "Not started"; } else
952 if (Status
== EFI_ALREADY_STARTED
) { Desc
= "Already started"; } else
953 if (Status
== EFI_ABORTED
) { Desc
= "Aborted"; } else
954 if (Status
== EFI_ICMP_ERROR
) { Desc
= "ICMP Error"; } else
955 if (Status
== EFI_TFTP_ERROR
) { Desc
= "TFTP Error"; } else
956 if (Status
== EFI_PROTOCOL_ERROR
) { Desc
= "Protocol Error"; } else
957 if (Status
== EFI_WARN_UNKNOWN_GLYPH
) { Desc
= "Warning Unknown Glyph"; } else
958 if (Status
== EFI_WARN_DELETE_FAILURE
) { Desc
= "Warning Delete Failure"; } else
959 if (Status
== EFI_WARN_WRITE_FAILURE
) { Desc
= "Warning Write Failure"; } else
960 if (Status
== EFI_WARN_BUFFER_TOO_SMALL
) { Desc
= "Warning Buffer Too Small"; }
963 // If we found a match, copy the message to the user's buffer. Otherwise
964 // sprint the hex status code to their buffer.
967 Size
= SPrint (Buffer
, BufferSize
, STRING_W ("%a"), Desc
);
969 Size
= SPrint (Buffer
, BufferSize
, STRING_W ("%X"), Status
);