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
);
578 // Flag space, +, 0, L & l are invalid for type p.
580 Flags
&= ~(PREFIX_BLANK
| PREFIX_SIGN
| LONG_TYPE
);
581 if (sizeof (VOID
*) > 4) {
583 Value
= VA_ARG (Marker
, UINT64
);
585 Value
= VA_ARG (Marker
, UINTN
);
587 Flags
|= PREFIX_ZERO
;
589 EfiValueToHexStr (TempBuffer
, Value
, Flags
, Width
);
590 UnicodeStr
= TempBuffer
;
592 for ( ;(*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++) {
593 Buffer
[Index
++] = *UnicodeStr
;
598 Flags
|= PREFIX_ZERO
;
599 Width
= sizeof (UINT64
) * 2;
602 // break skiped on purpose
605 if ((Flags
& LONG_TYPE
) == LONG_TYPE
) {
606 Value
= VA_ARG (Marker
, UINT64
);
608 Value
= VA_ARG (Marker
, UINTN
);
611 EfiValueToHexStr (TempBuffer
, Value
, Flags
, Width
);
612 UnicodeStr
= TempBuffer
;
614 for (; (*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++) {
615 Buffer
[Index
++] = *UnicodeStr
;
620 if ((Flags
& LONG_TYPE
) == LONG_TYPE
) {
621 Value
= VA_ARG (Marker
, UINT64
);
623 Value
= (UINTN
) VA_ARG (Marker
, UINTN
);
626 EfiValueToString (TempBuffer
, Value
, Flags
, Width
);
627 UnicodeStr
= TempBuffer
;
629 for (; (*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++) {
630 Buffer
[Index
++] = *UnicodeStr
;
636 UnicodeStr
= (CHAR16
*) VA_ARG (Marker
, CHAR_W
*);
637 if (UnicodeStr
== NULL
) {
638 UnicodeStr
= L
"<null string>";
641 for (Count
= 0; (*UnicodeStr
!= '\0') && (Index
< NumberOfCharacters
- 1); UnicodeStr
++, Count
++) {
642 Buffer
[Index
++] = *UnicodeStr
;
645 // Add padding if needed
647 for (; (Count
< Width
) && (Index
< NumberOfCharacters
- 1); Count
++) {
648 Buffer
[Index
++] = ' ';
654 AsciiStr
= (CHAR8
*) VA_ARG (Marker
, CHAR8
*);
655 if (AsciiStr
== NULL
) {
656 AsciiStr
= (CHAR8
*) "<null string>";
659 for (Count
= 0; (*AsciiStr
!= '\0') && (Index
< NumberOfCharacters
- 1); AsciiStr
++, Count
++) {
660 Buffer
[Index
++] = (CHAR_W
) * AsciiStr
;
663 // Add padding if needed
665 for (; (Count
< Width
) && (Index
< NumberOfCharacters
- 1); Count
++) {
666 Buffer
[Index
++] = ' ';
671 Buffer
[Index
++] = (CHAR_W
) VA_ARG (Marker
, UINTN
);
675 TmpGUID
= VA_ARG (Marker
, EFI_GUID
*);
676 if (TmpGUID
!= NULL
) {
677 Index
+= GuidToString (
686 Index
+= TimeToString (
687 VA_ARG (Marker
, EFI_TIME
*),
694 Index
+= EfiStatusToString (
695 VA_ARG (Marker
, EFI_STATUS
),
702 Buffer
[Index
++] = *Format
;
707 // if the type is unknown print it to the screen
709 Buffer
[Index
++] = *Format
;
712 BufferLeft
= BufferSize
- Index
* sizeof (CHAR_W
);
716 Buffer
[Index
++] = '\0';
718 return &Buffer
[Index
] - StartOfBuffer
;
727 IN OUT VA_LIST
*Marker
733 VSPrint worker function that parses flag and width information from the
734 Format string and returns the next index into the Format string that needs
735 to be parsed. See file headed for details of Flag and Width.
739 Format - Current location in the VSPrint format string.
741 Flags - Returns flags
743 Width - Returns width of element
745 Marker - Vararg list that may be paritally consumed and returned.
749 Pointer indexed into the Format string for all the information parsed
759 for (Done
= FALSE
; !Done
;) {
765 *Flags
|= LEFT_JUSTIFY
;
769 *Flags
|= PREFIX_SIGN
;
773 *Flags
|= PREFIX_BLANK
;
777 *Flags
|= COMMA_TYPE
;
786 *Width
= VA_ARG (*Marker
, UINTN
);
790 *Flags
|= PREFIX_ZERO
;
803 Count
= (Count
* 10) +*Format
- '0';
805 } while ((*Format
>= '0') && (*Format
<= '9'));
829 VSPrint worker function that prints an EFI_GUID.
833 Guid - Pointer to GUID to print.
835 Buffer - Buffe to print Guid into.
837 BufferSize - Size of Buffer.
841 Number of characters printed.
850 STRING_W ("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"),
854 (UINTN
)Guid
->Data4
[0],
855 (UINTN
)Guid
->Data4
[1],
856 (UINTN
)Guid
->Data4
[2],
857 (UINTN
)Guid
->Data4
[3],
858 (UINTN
)Guid
->Data4
[4],
859 (UINTN
)Guid
->Data4
[5],
860 (UINTN
)Guid
->Data4
[6],
861 (UINTN
)Guid
->Data4
[7]
865 // SPrint will null terminate the string. The -1 skips the null
882 VSPrint worker function that prints EFI_TIME.
886 Time - Pointer to EFI_TIME sturcture to print.
888 Buffer - Buffer to print Time into.
890 BufferSize - Size of Buffer.
894 Number of characters printed.
903 STRING_W ("%02d/%02d/%04d %02d:%02d"),
912 // SPrint will null terminate the string. The -1 skips the null
920 IN EFI_STATUS Status
,
928 VSPrint worker function that prints EFI_STATUS as a string. If string is
929 not known a hex value will be printed.
933 Status - EFI_STATUS sturcture to print.
935 Buffer - Buffer to print EFI_STATUS message string into.
937 BufferSize - Size of Buffer.
941 Number of characters printed.
951 // Can't use global Status String Array as UINTN is not constant for EBC
953 if (Status
== EFI_SUCCESS
) { Desc
= (CHAR8
*) "Success"; } else
954 if (Status
== EFI_LOAD_ERROR
) { Desc
= (CHAR8
*) "Load Error"; } else
955 if (Status
== EFI_INVALID_PARAMETER
) { Desc
= (CHAR8
*) "Invalid Parameter"; } else
956 if (Status
== EFI_UNSUPPORTED
) { Desc
= (CHAR8
*) "Unsupported"; } else
957 if (Status
== EFI_BAD_BUFFER_SIZE
) { Desc
= (CHAR8
*) "Bad Buffer Size"; } else
958 if (Status
== EFI_BUFFER_TOO_SMALL
) { Desc
= (CHAR8
*) "Buffer Too Small"; } else
959 if (Status
== EFI_NOT_READY
) { Desc
= (CHAR8
*) "Not Ready"; } else
960 if (Status
== EFI_DEVICE_ERROR
) { Desc
= (CHAR8
*) "Device Error"; } else
961 if (Status
== EFI_WRITE_PROTECTED
) { Desc
= (CHAR8
*) "Write Protected"; } else
962 if (Status
== EFI_OUT_OF_RESOURCES
) { Desc
= (CHAR8
*) "Out of Resources"; } else
963 if (Status
== EFI_VOLUME_CORRUPTED
) { Desc
= (CHAR8
*) "Volume Corrupt"; } else
964 if (Status
== EFI_VOLUME_FULL
) { Desc
= (CHAR8
*) "Volume Full"; } else
965 if (Status
== EFI_NO_MEDIA
) { Desc
= (CHAR8
*) "No Media"; } else
966 if (Status
== EFI_MEDIA_CHANGED
) { Desc
= (CHAR8
*) "Media changed"; } else
967 if (Status
== EFI_NOT_FOUND
) { Desc
= (CHAR8
*) "Not Found"; } else
968 if (Status
== EFI_ACCESS_DENIED
) { Desc
= (CHAR8
*) "Access Denied"; } else
969 if (Status
== EFI_NO_RESPONSE
) { Desc
= (CHAR8
*) "No Response"; } else
970 if (Status
== EFI_NO_MAPPING
) { Desc
= (CHAR8
*) "No mapping"; } else
971 if (Status
== EFI_TIMEOUT
) { Desc
= (CHAR8
*) "Time out"; } else
972 if (Status
== EFI_NOT_STARTED
) { Desc
= (CHAR8
*) "Not started"; } else
973 if (Status
== EFI_ALREADY_STARTED
) { Desc
= (CHAR8
*) "Already started"; } else
974 if (Status
== EFI_ABORTED
) { Desc
= (CHAR8
*) "Aborted"; } else
975 if (Status
== EFI_ICMP_ERROR
) { Desc
= (CHAR8
*) "ICMP Error"; } else
976 if (Status
== EFI_TFTP_ERROR
) { Desc
= (CHAR8
*) "TFTP Error"; } else
977 if (Status
== EFI_PROTOCOL_ERROR
) { Desc
= (CHAR8
*) "Protocol Error"; } else
978 if (Status
== EFI_WARN_UNKNOWN_GLYPH
) { Desc
= (CHAR8
*) "Warning Unknown Glyph"; } else
979 if (Status
== EFI_WARN_DELETE_FAILURE
) { Desc
= (CHAR8
*) "Warning Delete Failure"; } else
980 if (Status
== EFI_WARN_WRITE_FAILURE
) { Desc
= (CHAR8
*) "Warning Write Failure"; } else
981 if (Status
== EFI_WARN_BUFFER_TOO_SMALL
) { Desc
= (CHAR8
*) "Warning Buffer Too Small"; }
984 // If we found a match, copy the message to the user's buffer. Otherwise
985 // sprint the hex status code to their buffer.
988 Size
= SPrint (Buffer
, BufferSize
, STRING_W ("%a"), Desc
);
990 Size
= SPrint (Buffer
, BufferSize
, STRING_W ("%X"), Status
);