3 Copyright (c) 2004 - 2006, 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 #include EFI_PROTOCOL_DEFINITION (Hii)
70 IN OUT VA_LIST
*Marker
77 IN OUT CHAR_W
*Buffer
,
85 IN OUT CHAR_W
*Buffer
,
97 static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors
[16] = {
98 0x00, 0x00, 0x00, 0x00,
99 0x98, 0x00, 0x00, 0x00,
100 0x00, 0x98, 0x00, 0x00,
101 0x98, 0x98, 0x00, 0x00,
102 0x00, 0x00, 0x98, 0x00,
103 0x98, 0x00, 0x98, 0x00,
104 0x00, 0x98, 0x98, 0x00,
105 0x98, 0x98, 0x98, 0x00,
106 0x10, 0x10, 0x10, 0x00,
107 0xff, 0x10, 0x10, 0x00,
108 0x10, 0xff, 0x10, 0x00,
109 0xff, 0xff, 0x10, 0x00,
110 0x10, 0x10, 0xff, 0x00,
111 0xf0, 0x10, 0xff, 0x00,
112 0x10, 0xff, 0xff, 0x00,
113 0xff, 0xff, 0xff, 0x00,
119 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
,
120 IN EFI_UGA_DRAW_PROTOCOL
*UgaDraw
,
121 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*Sto
,
124 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Foreground
,
125 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Background
,
133 Display string worker for: Print, PrintAt, IPrint, IPrintAt
137 GraphicsOutput - Graphics output protocol interface
139 UgaDraw - UGA draw protocol interface
141 Sto - Simple text out protocol interface
143 X - X coordinate to start printing
145 Y - Y coordinate to start printing
147 Foreground - Foreground color
149 Background - Background color
153 args - Print arguments
157 EFI_SUCCESS - success
158 EFI_OUT_OF_RESOURCES - out of resources
168 CHAR16
*UnicodeWeight
;
169 EFI_NARROW_GLYPH
*Glyph
;
170 EFI_HII_PROTOCOL
*Hii
;
171 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*LineBuffer
;
172 UINT32 HorizontalResolution
;
173 UINT32 VerticalResolution
;
182 // For now, allocate an arbitrarily long buffer
184 Buffer
= EfiLibAllocateZeroPool (0x10000);
185 if (Buffer
== NULL
) {
186 return EFI_OUT_OF_RESOURCES
;
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 LineBufferLen
= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * HorizontalResolution
* GLYPH_HEIGHT
;
198 LineBuffer
= EfiLibAllocatePool (LineBufferLen
);
199 if (LineBuffer
== NULL
) {
200 gBS
->FreePool (Buffer
);
201 return EFI_OUT_OF_RESOURCES
;
204 Status
= gBS
->LocateProtocol (&gEfiHiiProtocolGuid
, NULL
, (VOID
**)&Hii
);
205 if (EFI_ERROR (Status
)) {
209 VSPrint (Buffer
, 0x10000, fmt
, args
);
211 UnicodeWeight
= (CHAR16
*) Buffer
;
213 for (Index
= 0; UnicodeWeight
[Index
] != 0; Index
++) {
214 if (UnicodeWeight
[Index
] == CHAR_BACKSPACE
||
215 UnicodeWeight
[Index
] == CHAR_LINEFEED
||
216 UnicodeWeight
[Index
] == CHAR_CARRIAGE_RETURN
) {
217 UnicodeWeight
[Index
] = 0;
221 BufferLen
= EfiStrLen (Buffer
);
223 if (GLYPH_WIDTH
* GLYPH_HEIGHT
* sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * BufferLen
> LineBufferLen
) {
224 Status
= EFI_INVALID_PARAMETER
;
228 for (Index
= 0; Index
< BufferLen
; Index
++) {
229 StringIndex
= (UINT16
) Index
;
230 Status
= Hii
->GetGlyph (Hii
, UnicodeWeight
, &StringIndex
, (UINT8
**) &Glyph
, &GlyphWidth
, &GlyphStatus
);
231 if (EFI_ERROR (Status
)) {
235 if (Foreground
== NULL
|| Background
== NULL
) {
236 Status
= Hii
->GlyphToBlt (
239 mEfiColors
[Sto
->Mode
->Attribute
& 0x0f],
240 mEfiColors
[Sto
->Mode
->Attribute
>> 4],
244 &LineBuffer
[Index
* GLYPH_WIDTH
]
247 Status
= Hii
->GlyphToBlt (
255 &LineBuffer
[Index
* GLYPH_WIDTH
]
261 // Blt a character to the screen
263 if (GraphicsOutput
!= NULL
) {
264 Status
= GraphicsOutput
->Blt (
272 GLYPH_WIDTH
* BufferLen
,
274 GLYPH_WIDTH
* BufferLen
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
277 Status
= UgaDraw
->Blt (
279 (EFI_UGA_PIXEL
*) LineBuffer
,
280 EfiUgaBltBufferToVideo
,
285 GLYPH_WIDTH
* BufferLen
,
287 GLYPH_WIDTH
* BufferLen
* sizeof (EFI_UGA_PIXEL
)
292 gBS
->FreePool (LineBuffer
);
293 gBS
->FreePool (Buffer
);
302 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*ForeGround
, OPTIONAL
303 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BackGround
, OPTIONAL
311 Prints a formatted unicode string to the default console
315 X - X coordinate to start printing
317 Y - Y coordinate to start printing
319 ForeGround - Foreground color
321 BackGround - Background color
325 ... - Print arguments
329 Length of string printed to the console
334 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
335 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
336 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*Sto
;
340 VA_START (Args
, Fmt
);
342 Handle
= gST
->ConsoleOutHandle
;
344 Status
= gBS
->HandleProtocol (
346 &gEfiGraphicsOutputProtocolGuid
,
347 (VOID
**)&GraphicsOutput
351 if (EFI_ERROR (Status
)) {
352 GraphicsOutput
= NULL
;
354 Status
= gBS
->HandleProtocol (
356 &gEfiUgaDrawProtocolGuid
,
360 if (EFI_ERROR (Status
)) {
365 Status
= gBS
->HandleProtocol (
367 &gEfiSimpleTextOutProtocolGuid
,
371 if (EFI_ERROR (Status
)) {
375 return _IPrint (GraphicsOutput
, UgaDraw
, Sto
, X
, Y
, ForeGround
, BackGround
, Fmt
, Args
);
383 IN CONST CHAR_W
*Format
,
390 SPrint function to process format and place the results in Buffer.
394 Buffer - Wide char buffer to print the results of the parsing of Format into.
396 BufferSize - Maximum number of characters to put into buffer. Zero means no
399 Format - Format string see file header for more details.
401 ... - Vararg list consumed by processing Format.
405 Number of characters printed.
412 VA_START (Marker
, Format
);
413 Return
= VSPrint (Buffer
, BufferSize
, Format
, Marker
);
421 OUT CHAR_W
*StartOfBuffer
,
423 IN CONST CHAR_W
*FormatString
,
430 VSPrint function to process format and place the results in Buffer. Since a
431 VA_LIST is used this rountine allows the nesting of Vararg routines. Thus
432 this is the main print working routine
436 StartOfBuffer - Unicode buffer to print the results of the parsing of Format into.
438 BufferSize - Maximum number of characters to put into buffer. Zero means
441 FormatString - Unicode format string see file header for more details.
443 Marker - Vararg list consumed by processing Format.
447 Number of characters printed.
451 CHAR16 TempBuffer
[CHARACTER_NUMBER_FOR_VALUE
];
460 UINTN NumberOfCharacters
;
466 // Process the format string. Stop if Buffer is over run.
469 Buffer
= StartOfBuffer
;
470 Format
= (CHAR_W
*) FormatString
;
471 NumberOfCharacters
= BufferSize
/ sizeof (CHAR_W
);
472 BufferLeft
= BufferSize
;
473 for (Index
= 0; (*Format
!= '\0') && (Index
< NumberOfCharacters
- 1); Format
++) {
474 if (*Format
!= '%') {
475 if ((*Format
== '\n') && (Index
< NumberOfCharacters
- 2)) {
477 // If carage return add line feed
479 Buffer
[Index
++] = '\r';
480 BufferLeft
-= sizeof (CHAR_W
);
483 Buffer
[Index
++] = *Format
;
484 BufferLeft
-= sizeof (CHAR_W
);
488 // Now it's time to parse what follows after %
490 Format
= GetFlagsAndWidth (Format
, &Flags
, &Width
, &Marker
);
493 Flags
|= PREFIX_ZERO
;
494 Width
= sizeof (UINT64
) * 2;
497 // break skiped on purpose
500 if ((Flags
& LONG_TYPE
) == LONG_TYPE
) {
501 Value
= VA_ARG (Marker
, UINT64
);
503 Value
= VA_ARG (Marker
, UINTN
);
506 EfiValueToHexStr (TempBuffer
, Value
, Flags
, Width
);
507 UnicodeStr
= TempBuffer
;
509 for (; (*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++) {
510 Buffer
[Index
++] = *UnicodeStr
;
515 if ((Flags
& LONG_TYPE
) == LONG_TYPE
) {
516 Value
= VA_ARG (Marker
, UINT64
);
518 Value
= (UINTN
) VA_ARG (Marker
, UINTN
);
521 EfiValueToString (TempBuffer
, Value
, Flags
, Width
);
522 UnicodeStr
= TempBuffer
;
524 for (; (*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++) {
525 Buffer
[Index
++] = *UnicodeStr
;
531 UnicodeStr
= (CHAR16
*) VA_ARG (Marker
, CHAR_W
*);
532 if (UnicodeStr
== NULL
) {
533 UnicodeStr
= L
"<null string>";
536 for (Count
= 0; (*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++, Count
++) {
537 Buffer
[Index
++] = *UnicodeStr
;
540 // Add padding if needed
542 for (; (Count
< Width
) && (Index
< NumberOfCharacters
- 1); Count
++) {
543 Buffer
[Index
++] = ' ';
549 AsciiStr
= (CHAR8
*) VA_ARG (Marker
, CHAR8
*);
550 if (AsciiStr
== NULL
) {
551 AsciiStr
= "<null string>";
554 for (Count
= 0; (*AsciiStr
!= '\0') && (Index
< NumberOfCharacters
- 1); AsciiStr
++, Count
++) {
555 Buffer
[Index
++] = (CHAR_W
) * AsciiStr
;
558 // Add padding if needed
560 for (; (Count
< Width
) && (Index
< NumberOfCharacters
- 1); Count
++) {
561 Buffer
[Index
++] = ' ';
566 Buffer
[Index
++] = (CHAR_W
) VA_ARG (Marker
, UINTN
);
570 TmpGUID
= VA_ARG (Marker
, EFI_GUID
*);
571 if (TmpGUID
!= NULL
) {
572 Index
+= GuidToString (
581 Index
+= TimeToString (
582 VA_ARG (Marker
, EFI_TIME
*),
589 Index
+= EfiStatusToString (
590 VA_ARG (Marker
, EFI_STATUS
),
597 Buffer
[Index
++] = *Format
;
602 // if the type is unknown print it to the screen
604 Buffer
[Index
++] = *Format
;
607 BufferLeft
= BufferSize
- Index
* sizeof (CHAR_W
);
611 Buffer
[Index
++] = '\0';
613 return &Buffer
[Index
] - StartOfBuffer
;
622 IN OUT VA_LIST
*Marker
628 VSPrint worker function that parses flag and width information from the
629 Format string and returns the next index into the Format string that needs
630 to be parsed. See file headed for details of Flag and Width.
634 Format - Current location in the VSPrint format string.
636 Flags - Returns flags
638 Width - Returns width of element
640 Marker - Vararg list that may be paritally consumed and returned.
644 Pointer indexed into the Format string for all the information parsed
654 for (Done
= FALSE
; !Done
;) {
660 *Flags
|= LEFT_JUSTIFY
;
664 *Flags
|= PREFIX_SIGN
;
668 *Flags
|= PREFIX_BLANK
;
672 *Flags
|= COMMA_TYPE
;
681 *Width
= VA_ARG (*Marker
, UINTN
);
685 *Flags
|= PREFIX_ZERO
;
698 Count
= (Count
* 10) +*Format
- '0';
700 } while ((*Format
>= '0') && (*Format
<= '9'));
724 VSPrint worker function that prints an EFI_GUID.
728 Guid - Pointer to GUID to print.
730 Buffer - Buffe to print Guid into.
732 BufferSize - Size of Buffer.
736 Number of characters printed.
745 STRING_W ("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"),
749 (UINTN
)Guid
->Data4
[0],
750 (UINTN
)Guid
->Data4
[1],
751 (UINTN
)Guid
->Data4
[2],
752 (UINTN
)Guid
->Data4
[3],
753 (UINTN
)Guid
->Data4
[4],
754 (UINTN
)Guid
->Data4
[5],
755 (UINTN
)Guid
->Data4
[6],
756 (UINTN
)Guid
->Data4
[7]
760 // SPrint will null terminate the string. The -1 skips the null
777 VSPrint worker function that prints EFI_TIME.
781 Time - Pointer to EFI_TIME sturcture to print.
783 Buffer - Buffer to print Time into.
785 BufferSize - Size of Buffer.
789 Number of characters printed.
798 STRING_W ("%02d/%02d/%04d %02d:%02d"),
807 // SPrint will null terminate the string. The -1 skips the null
815 IN EFI_STATUS Status
,
823 VSPrint worker function that prints EFI_STATUS as a string. If string is
824 not known a hex value will be printed.
828 Status - EFI_STATUS sturcture to print.
830 Buffer - Buffer to print EFI_STATUS message string into.
832 BufferSize - Size of Buffer.
836 Number of characters printed.
846 // Can't use global Status String Array as UINTN is not constant for EBC
848 if (Status
== EFI_SUCCESS
) { Desc
= "Success"; } else
849 if (Status
== EFI_LOAD_ERROR
) { Desc
= "Load Error"; } else
850 if (Status
== EFI_INVALID_PARAMETER
) { Desc
= "Invalid Parameter"; } else
851 if (Status
== EFI_UNSUPPORTED
) { Desc
= "Unsupported"; } else
852 if (Status
== EFI_BAD_BUFFER_SIZE
) { Desc
= "Bad Buffer Size"; } else
853 if (Status
== EFI_BUFFER_TOO_SMALL
) { Desc
= "Buffer Too Small"; } else
854 if (Status
== EFI_NOT_READY
) { Desc
= "Not Ready"; } else
855 if (Status
== EFI_DEVICE_ERROR
) { Desc
= "Device Error"; } else
856 if (Status
== EFI_WRITE_PROTECTED
) { Desc
= "Write Protected"; } else
857 if (Status
== EFI_OUT_OF_RESOURCES
) { Desc
= "Out of Resources"; } else
858 if (Status
== EFI_VOLUME_CORRUPTED
) { Desc
= "Volume Corrupt"; } else
859 if (Status
== EFI_VOLUME_FULL
) { Desc
= "Volume Full"; } else
860 if (Status
== EFI_NO_MEDIA
) { Desc
= "No Media"; } else
861 if (Status
== EFI_MEDIA_CHANGED
) { Desc
= "Media changed"; } else
862 if (Status
== EFI_NOT_FOUND
) { Desc
= "Not Found"; } else
863 if (Status
== EFI_ACCESS_DENIED
) { Desc
= "Access Denied"; } else
864 if (Status
== EFI_NO_RESPONSE
) { Desc
= "No Response"; } else
865 if (Status
== EFI_NO_MAPPING
) { Desc
= "No mapping"; } else
866 if (Status
== EFI_TIMEOUT
) { Desc
= "Time out"; } else
867 if (Status
== EFI_NOT_STARTED
) { Desc
= "Not started"; } else
868 if (Status
== EFI_ALREADY_STARTED
) { Desc
= "Already started"; } else
869 if (Status
== EFI_ABORTED
) { Desc
= "Aborted"; } else
870 if (Status
== EFI_ICMP_ERROR
) { Desc
= "ICMP Error"; } else
871 if (Status
== EFI_TFTP_ERROR
) { Desc
= "TFTP Error"; } else
872 if (Status
== EFI_PROTOCOL_ERROR
) { Desc
= "Protocol Error"; } else
873 if (Status
== EFI_WARN_UNKNOWN_GLYPH
) { Desc
= "Warning Unknown Glyph"; } else
874 if (Status
== EFI_WARN_DELETE_FAILURE
) { Desc
= "Warning Delete Failure"; } else
875 if (Status
== EFI_WARN_WRITE_FAILURE
) { Desc
= "Warning Write Failure"; } else
876 if (Status
== EFI_WARN_BUFFER_TOO_SMALL
) { Desc
= "Warning Buffer Too Small"; }
879 // If we found a match, copy the message to the user's buffer. Otherwise
880 // sprint the hex status code to their buffer.
883 Size
= SPrint (Buffer
, BufferSize
, STRING_W ("%a"), Desc
);
885 Size
= SPrint (Buffer
, BufferSize
, STRING_W ("%X"), Status
);