]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Foundation/Library/Dxe/Graphics/Print.c
Add more check to make sure code run safely.
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / Dxe / Graphics / Print.c
1 /*++
2
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
8
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.
11
12 Module Name:
13
14 Print.c
15
16 Abstract:
17
18 Basic Ascii AvSPrintf() function named VSPrint(). VSPrint() enables very
19 simple implemenation of SPrint() and Print() to support debug.
20
21 You can not Print more than EFI_DRIVER_LIB_MAX_PRINT_BUFFER characters at a
22 time. This makes the implementation very simple.
23
24 VSPrint, Print, SPrint format specification has the follwoing form
25
26 %[flags][width]type
27
28 flags:
29 '-' - Left justify
30 '+' - Prefix a sign
31 ' ' - Prefix a blank
32 ',' - Place commas in numberss
33 '0' - Prefix for width with zeros
34 'l' - UINT64
35 'L' - UINT64
36
37 width:
38 '*' - Get width from a UINTN argumnet from the argument list
39 Decimal number that represents width of print
40
41 type:
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
51 '%' - Print a %
52
53 --*/
54
55 #include "Tiano.h"
56 #include "EfiDriverLib.h"
57 #include "TianoCommon.h"
58 #include "EfiCommonLib.h"
59 #include "PrintWidth.h"
60 #include "EfiPrintLib.h"
61 #include "Print.h"
62 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
63 #include EFI_PROTOCOL_DEFINITION (HiiFont)
64 #else
65 #include EFI_PROTOCOL_DEFINITION (Hii)
66 #endif
67
68 STATIC
69 CHAR_W *
70 GetFlagsAndWidth (
71 IN CHAR_W *Format,
72 OUT UINTN *Flags,
73 OUT UINTN *Width,
74 IN OUT VA_LIST *Marker
75 );
76
77 STATIC
78 UINTN
79 GuidToString (
80 IN EFI_GUID *Guid,
81 IN OUT CHAR_W *Buffer,
82 IN UINTN BufferSize
83 );
84
85 STATIC
86 UINTN
87 TimeToString (
88 IN EFI_TIME *Time,
89 IN OUT CHAR_W *Buffer,
90 IN UINTN BufferSize
91 );
92
93 STATIC
94 UINTN
95 EfiStatusToString (
96 IN EFI_STATUS Status,
97 OUT CHAR_W *Buffer,
98 IN UINTN BufferSize
99 );
100
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},
118 };
119
120
121 UINTN
122 _IPrint (
123 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
124 IN EFI_UGA_DRAW_PROTOCOL *UgaDraw,
125 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *Sto,
126 IN UINTN X,
127 IN UINTN Y,
128 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground,
129 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background,
130 IN CHAR16 *fmt,
131 IN VA_LIST args
132 )
133 /*++
134
135 Routine Description:
136
137 Display string worker for: Print, PrintAt, IPrint, IPrintAt
138
139 Arguments:
140
141 GraphicsOutput - Graphics output protocol interface
142
143 UgaDraw - UGA draw protocol interface
144
145 Sto - Simple text out protocol interface
146
147 X - X coordinate to start printing
148
149 Y - Y coordinate to start printing
150
151 Foreground - Foreground color
152
153 Background - Background color
154
155 fmt - Format string
156
157 args - Print arguments
158
159 Returns:
160
161 Length of string printed to the console
162
163 --*/
164 {
165 VOID *Buffer;
166 EFI_STATUS Status;
167 UINTN Index;
168 CHAR16 *UnicodeWeight;
169 UINT32 HorizontalResolution;
170 UINT32 VerticalResolution;
171 UINT32 ColorDepth;
172 UINT32 RefreshRate;
173 UINTN BufferLen;
174 UINTN LineBufferLen;
175 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
176 EFI_HII_FONT_PROTOCOL *HiiFont;
177 EFI_IMAGE_OUTPUT *Blt;
178 EFI_FONT_DISPLAY_INFO *FontInfo;
179 #else
180 EFI_HII_PROTOCOL *Hii;
181 UINT16 GlyphWidth;
182 UINT32 GlyphStatus;
183 UINT16 StringIndex;
184 EFI_NARROW_GLYPH *Glyph;
185 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LineBuffer;
186 #endif
187
188 //
189 // For now, allocate an arbitrarily long buffer
190 //
191 Buffer = EfiLibAllocateZeroPool (0x10000);
192 if (Buffer == NULL) {
193 return 0;
194 }
195
196 if (GraphicsOutput != NULL) {
197 HorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
198 VerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;
199 } else {
200 UgaDraw->GetMode (UgaDraw, &HorizontalResolution, &VerticalResolution, &ColorDepth, &RefreshRate);
201 }
202 ASSERT ((HorizontalResolution != 0) && (VerticalResolution !=0));
203
204 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
205 Blt = NULL;
206 FontInfo = NULL;
207 ASSERT (GraphicsOutput != NULL);
208 Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL, (VOID **) &HiiFont);
209 if (EFI_ERROR (Status)) {
210 goto Error;
211 }
212 #else
213 LineBuffer = NULL;
214 Status = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, (VOID**)&Hii);
215 if (EFI_ERROR (Status)) {
216 goto Error;
217 }
218 LineBufferLen = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * HorizontalResolution * GLYPH_HEIGHT;
219 LineBuffer = EfiLibAllocatePool (LineBufferLen);
220 if (LineBuffer == NULL) {
221 Status = EFI_OUT_OF_RESOURCES;
222 goto Error;
223 }
224 #endif
225
226 VSPrint (Buffer, 0x10000, fmt, args);
227
228 UnicodeWeight = (CHAR16 *) Buffer;
229
230 for (Index = 0; UnicodeWeight[Index] != 0; Index++) {
231 if (UnicodeWeight[Index] == CHAR_BACKSPACE ||
232 UnicodeWeight[Index] == CHAR_LINEFEED ||
233 UnicodeWeight[Index] == CHAR_CARRIAGE_RETURN) {
234 UnicodeWeight[Index] = 0;
235 }
236 }
237
238 BufferLen = EfiStrLen (Buffer);
239
240
241 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
242 LineBufferLen = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * HorizontalResolution * EFI_GLYPH_HEIGHT;
243 if (EFI_GLYPH_WIDTH * EFI_GLYPH_HEIGHT * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * BufferLen > LineBufferLen) {
244 Status = EFI_INVALID_PARAMETER;
245 goto Error;
246 }
247
248 Blt = (EFI_IMAGE_OUTPUT *) EfiLibAllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
249 if (Blt == NULL) {
250 Status = EFI_OUT_OF_RESOURCES;
251 goto Error;
252 }
253
254 Blt->Width = (UINT16) (HorizontalResolution);
255 Blt->Height = (UINT16) (VerticalResolution);
256 Blt->Image.Screen = GraphicsOutput;
257
258 FontInfo = (EFI_FONT_DISPLAY_INFO *) EfiLibAllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO));
259 if (FontInfo == NULL) {
260 Status = EFI_OUT_OF_RESOURCES;
261 goto Error;
262 }
263 if (Foreground != NULL) {
264 EfiCopyMem (&FontInfo->ForegroundColor, Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
265 } else {
266 EfiCopyMem (
267 &FontInfo->ForegroundColor,
268 &mEfiColors[Sto->Mode->Attribute & 0x0f],
269 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
270 );
271 }
272 if (Background != NULL) {
273 EfiCopyMem (&FontInfo->BackgroundColor, Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
274 } else {
275 EfiCopyMem (
276 &FontInfo->BackgroundColor,
277 &mEfiColors[Sto->Mode->Attribute >> 4],
278 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
279 );
280 }
281
282 Status = HiiFont->StringToImage (
283 HiiFont,
284 EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_DIRECT_TO_SCREEN,
285 Buffer,
286 FontInfo,
287 &Blt,
288 X,
289 Y,
290 NULL,
291 NULL,
292 NULL
293 );
294
295 #else
296 GlyphStatus = 0;
297
298 if (GLYPH_WIDTH * GLYPH_HEIGHT * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * BufferLen > LineBufferLen) {
299 Status = EFI_INVALID_PARAMETER;
300 goto Error;
301 }
302
303 for (Index = 0; Index < BufferLen; Index++) {
304 StringIndex = (UINT16) Index;
305 Status = Hii->GetGlyph (Hii, UnicodeWeight, &StringIndex, (UINT8 **) &Glyph, &GlyphWidth, &GlyphStatus);
306 if (EFI_ERROR (Status)) {
307 goto Error;
308 }
309
310 if (Foreground == NULL || Background == NULL) {
311 Status = Hii->GlyphToBlt (
312 Hii,
313 (UINT8 *) Glyph,
314 mEfiColors[Sto->Mode->Attribute & 0x0f],
315 mEfiColors[Sto->Mode->Attribute >> 4],
316 BufferLen,
317 GlyphWidth,
318 GLYPH_HEIGHT,
319 &LineBuffer[Index * GLYPH_WIDTH]
320 );
321 } else {
322 Status = Hii->GlyphToBlt (
323 Hii,
324 (UINT8 *) Glyph,
325 *Foreground,
326 *Background,
327 BufferLen,
328 GlyphWidth,
329 GLYPH_HEIGHT,
330 &LineBuffer[Index * GLYPH_WIDTH]
331 );
332 }
333 }
334
335 //
336 // Blt a character to the screen
337 //
338 if (GraphicsOutput != NULL) {
339 Status = GraphicsOutput->Blt (
340 GraphicsOutput,
341 LineBuffer,
342 EfiBltBufferToVideo,
343 0,
344 0,
345 X,
346 Y,
347 GLYPH_WIDTH * BufferLen,
348 GLYPH_HEIGHT,
349 GLYPH_WIDTH * BufferLen * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
350 );
351 } else {
352 Status = UgaDraw->Blt (
353 UgaDraw,
354 (EFI_UGA_PIXEL *) LineBuffer,
355 EfiUgaBltBufferToVideo,
356 0,
357 0,
358 X,
359 Y,
360 GLYPH_WIDTH * BufferLen,
361 GLYPH_HEIGHT,
362 GLYPH_WIDTH * BufferLen * sizeof (EFI_UGA_PIXEL)
363 );
364 }
365
366 #endif
367
368 Error:
369 #if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
370 EfiLibSafeFreePool (Blt);
371 EfiLibSafeFreePool (FontInfo);
372 #else
373 EfiLibSafeFreePool (LineBuffer);
374 #endif
375 gBS->FreePool (Buffer);
376
377 if (EFI_ERROR (Status)) {
378 return 0;
379 }
380
381 return BufferLen;
382 }
383
384
385 UINTN
386 PrintXY (
387 IN UINTN X,
388 IN UINTN Y,
389 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ForeGround, OPTIONAL
390 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BackGround, OPTIONAL
391 IN CHAR_W *Fmt,
392 ...
393 )
394 /*++
395
396 Routine Description:
397
398 Prints a formatted unicode string to the default console
399
400 Arguments:
401
402 X - X coordinate to start printing
403
404 Y - Y coordinate to start printing
405
406 ForeGround - Foreground color
407
408 BackGround - Background color
409
410 Fmt - Format string
411
412 ... - Print arguments
413
414 Returns:
415
416 Length of string printed to the console
417
418 --*/
419 {
420 EFI_HANDLE Handle;
421 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
422 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
423 EFI_SIMPLE_TEXT_OUT_PROTOCOL *Sto;
424 EFI_STATUS Status;
425 VA_LIST Args;
426
427 VA_START (Args, Fmt);
428
429 Handle = gST->ConsoleOutHandle;
430
431 Status = gBS->HandleProtocol (
432 Handle,
433 &gEfiGraphicsOutputProtocolGuid,
434 (VOID**)&GraphicsOutput
435 );
436
437 UgaDraw = NULL;
438 if (EFI_ERROR (Status)) {
439 GraphicsOutput = NULL;
440
441 Status = gBS->HandleProtocol (
442 Handle,
443 &gEfiUgaDrawProtocolGuid,
444 (VOID**)&UgaDraw
445 );
446
447 if (EFI_ERROR (Status) || (UgaDraw == NULL)) {
448 return 0;
449 }
450 }
451
452 Sto = NULL;
453 Status = gBS->HandleProtocol (
454 Handle,
455 &gEfiSimpleTextOutProtocolGuid,
456 (VOID**)&Sto
457 );
458
459 if (EFI_ERROR (Status) || (Sto == NULL)) {
460 return 0;
461 }
462
463 return _IPrint (GraphicsOutput, UgaDraw, Sto, X, Y, ForeGround, BackGround, Fmt, Args);
464 }
465
466
467 UINTN
468 SPrint (
469 OUT CHAR_W *Buffer,
470 IN UINTN BufferSize,
471 IN CONST CHAR_W *Format,
472 ...
473 )
474 /*++
475
476 Routine Description:
477
478 SPrint function to process format and place the results in Buffer.
479
480 Arguments:
481
482 Buffer - Wide char buffer to print the results of the parsing of Format into.
483
484 BufferSize - Maximum number of characters to put into buffer. Zero means no
485 limit.
486
487 Format - Format string see file header for more details.
488
489 ... - Vararg list consumed by processing Format.
490
491 Returns:
492
493 Number of characters printed.
494
495 --*/
496 {
497 UINTN Return;
498 VA_LIST Marker;
499
500 VA_START (Marker, Format);
501 Return = VSPrint (Buffer, BufferSize, Format, Marker);
502 VA_END (Marker);
503
504 return Return;
505 }
506
507 UINTN
508 EFIAPI
509 VSPrint (
510 OUT CHAR_W *StartOfBuffer,
511 IN UINTN BufferSize,
512 IN CONST CHAR_W *FormatString,
513 IN VA_LIST Marker
514 )
515 /*++
516
517 Routine Description:
518
519 VSPrint function to process format and place the results in Buffer. Since a
520 VA_LIST is used this rountine allows the nesting of Vararg routines. Thus
521 this is the main print working routine
522
523 Arguments:
524
525 StartOfBuffer - Unicode buffer to print the results of the parsing of Format into.
526
527 BufferSize - Maximum number of characters to put into buffer. Zero means
528 no limit.
529
530 FormatString - Unicode format string see file header for more details.
531
532 Marker - Vararg list consumed by processing Format.
533
534 Returns:
535
536 Number of characters printed.
537
538 --*/
539 {
540 CHAR16 TempBuffer[CHARACTER_NUMBER_FOR_VALUE];
541 CHAR_W *Buffer;
542 CHAR8 *AsciiStr;
543 CHAR16 *UnicodeStr;
544 CHAR_W *Format;
545 UINTN Index;
546 UINTN Flags;
547 UINTN Width;
548 UINTN Count;
549 UINTN NumberOfCharacters;
550 UINTN BufferLeft;
551 UINT64 Value;
552 EFI_GUID *TmpGUID;
553
554 //
555 // Process the format string. Stop if Buffer is over run.
556 //
557
558 Buffer = StartOfBuffer;
559 Format = (CHAR_W *) FormatString;
560 NumberOfCharacters = BufferSize / sizeof (CHAR_W);
561 BufferLeft = BufferSize;
562 for (Index = 0; (*Format != '\0') && (Index < NumberOfCharacters - 1); Format++) {
563 if (*Format != '%') {
564 if ((*Format == '\n') && (Index < NumberOfCharacters - 2)) {
565 //
566 // If carage return add line feed
567 //
568 Buffer[Index++] = '\r';
569 BufferLeft -= sizeof (CHAR_W);
570 }
571
572 Buffer[Index++] = *Format;
573 BufferLeft -= sizeof (CHAR_W);
574 } else {
575
576 //
577 // Now it's time to parse what follows after %
578 //
579 Format = GetFlagsAndWidth (Format, &Flags, &Width, &Marker);
580 switch (*Format) {
581 case 'p':
582 //
583 // Flag space, +, 0, L & l are invalid for type p.
584 //
585 Flags &= ~(PREFIX_BLANK| PREFIX_SIGN | LONG_TYPE);
586 if (sizeof (VOID *) > 4) {
587 Flags |= LONG_TYPE;
588 Value = VA_ARG (Marker, UINT64);
589 } else {
590 Value = VA_ARG (Marker, UINTN);
591 }
592 Flags |= PREFIX_ZERO;
593
594 EfiValueToHexStr (TempBuffer, Value, Flags, Width);
595 UnicodeStr = TempBuffer;
596
597 for ( ;(*UnicodeStr != '\0') && (Index < NumberOfCharacters - 1); UnicodeStr++) {
598 Buffer[Index++] = *UnicodeStr;
599 }
600 break;
601
602 case 'X':
603 Flags |= PREFIX_ZERO;
604 Width = sizeof (UINT64) * 2;
605
606 //
607 // break skiped on purpose
608 //
609 case 'x':
610 if ((Flags & LONG_TYPE) == LONG_TYPE) {
611 Value = VA_ARG (Marker, UINT64);
612 } else {
613 Value = VA_ARG (Marker, UINTN);
614 }
615
616 EfiValueToHexStr (TempBuffer, Value, Flags, Width);
617 UnicodeStr = TempBuffer;
618
619 for (; (*UnicodeStr != '\0') && (Index < NumberOfCharacters - 1); UnicodeStr++) {
620 Buffer[Index++] = *UnicodeStr;
621 }
622 break;
623
624 case 'd':
625 if ((Flags & LONG_TYPE) == LONG_TYPE) {
626 Value = VA_ARG (Marker, UINT64);
627 } else {
628 Value = (UINTN) VA_ARG (Marker, UINTN);
629 }
630
631 EfiValueToString (TempBuffer, Value, Flags, Width);
632 UnicodeStr = TempBuffer;
633
634 for (; (*UnicodeStr != '\0') && (Index < NumberOfCharacters - 1); UnicodeStr++) {
635 Buffer[Index++] = *UnicodeStr;
636 }
637 break;
638
639 case 's':
640 case 'S':
641 UnicodeStr = (CHAR16 *) VA_ARG (Marker, CHAR_W *);
642 if (UnicodeStr == NULL) {
643 UnicodeStr = L"<null string>";
644 }
645
646 for (Count = 0; (*UnicodeStr != '\0') && (Index < NumberOfCharacters - 1); UnicodeStr++, Count++) {
647 Buffer[Index++] = *UnicodeStr;
648 }
649 //
650 // Add padding if needed
651 //
652 for (; (Count < Width) && (Index < NumberOfCharacters - 1); Count++) {
653 Buffer[Index++] = ' ';
654 }
655
656 break;
657
658 case 'a':
659 AsciiStr = (CHAR8 *) VA_ARG (Marker, CHAR8 *);
660 if (AsciiStr == NULL) {
661 AsciiStr = (CHAR8 *) "<null string>";
662 }
663
664 for (Count = 0; (*AsciiStr != '\0') && (Index < NumberOfCharacters - 1); AsciiStr++, Count++) {
665 Buffer[Index++] = (CHAR_W) * AsciiStr;
666 }
667 //
668 // Add padding if needed
669 //
670 for (; (Count < Width) && (Index < NumberOfCharacters - 1); Count++) {
671 Buffer[Index++] = ' ';
672 }
673 break;
674
675 case 'c':
676 Buffer[Index++] = (CHAR_W) VA_ARG (Marker, UINTN);
677 break;
678
679 case 'g':
680 TmpGUID = VA_ARG (Marker, EFI_GUID *);
681 if (TmpGUID != NULL) {
682 Index += GuidToString (
683 TmpGUID,
684 &Buffer[Index],
685 BufferLeft
686 );
687 }
688 break;
689
690 case 't':
691 Index += TimeToString (
692 VA_ARG (Marker, EFI_TIME *),
693 &Buffer[Index],
694 BufferLeft
695 );
696 break;
697
698 case 'r':
699 Index += EfiStatusToString (
700 VA_ARG (Marker, EFI_STATUS),
701 &Buffer[Index],
702 BufferLeft
703 );
704 break;
705
706 case '%':
707 Buffer[Index++] = *Format;
708 break;
709
710 default:
711 //
712 // if the type is unknown print it to the screen
713 //
714 Buffer[Index++] = *Format;
715 }
716
717 BufferLeft = BufferSize - Index * sizeof (CHAR_W);
718 }
719 }
720
721 Buffer[Index++] = '\0';
722
723 return &Buffer[Index] - StartOfBuffer;
724 }
725
726 STATIC
727 CHAR_W *
728 GetFlagsAndWidth (
729 IN CHAR_W *Format,
730 OUT UINTN *Flags,
731 OUT UINTN *Width,
732 IN OUT VA_LIST *Marker
733 )
734 /*++
735
736 Routine Description:
737
738 VSPrint worker function that parses flag and width information from the
739 Format string and returns the next index into the Format string that needs
740 to be parsed. See file headed for details of Flag and Width.
741
742 Arguments:
743
744 Format - Current location in the VSPrint format string.
745
746 Flags - Returns flags
747
748 Width - Returns width of element
749
750 Marker - Vararg list that may be paritally consumed and returned.
751
752 Returns:
753
754 Pointer indexed into the Format string for all the information parsed
755 by this routine.
756
757 --*/
758 {
759 UINTN Count;
760 BOOLEAN Done;
761
762 *Flags = 0;
763 *Width = 0;
764 for (Done = FALSE; !Done;) {
765 Format++;
766
767 switch (*Format) {
768
769 case '-':
770 *Flags |= LEFT_JUSTIFY;
771 break;
772
773 case '+':
774 *Flags |= PREFIX_SIGN;
775 break;
776
777 case ' ':
778 *Flags |= PREFIX_BLANK;
779 break;
780
781 case ',':
782 *Flags |= COMMA_TYPE;
783 break;
784
785 case 'L':
786 case 'l':
787 *Flags |= LONG_TYPE;
788 break;
789
790 case '*':
791 *Width = VA_ARG (*Marker, UINTN);
792 break;
793
794 case '0':
795 *Flags |= PREFIX_ZERO;
796
797 case '1':
798 case '2':
799 case '3':
800 case '4':
801 case '5':
802 case '6':
803 case '7':
804 case '8':
805 case '9':
806 Count = 0;
807 do {
808 Count = (Count * 10) +*Format - '0';
809 Format++;
810 } while ((*Format >= '0') && (*Format <= '9'));
811 Format--;
812 *Width = Count;
813 break;
814
815 default:
816 Done = TRUE;
817 }
818 }
819
820 return Format;
821 }
822
823 STATIC
824 UINTN
825 GuidToString (
826 IN EFI_GUID *Guid,
827 IN CHAR_W *Buffer,
828 IN UINTN BufferSize
829 )
830 /*++
831
832 Routine Description:
833
834 VSPrint worker function that prints an EFI_GUID.
835
836 Arguments:
837
838 Guid - Pointer to GUID to print.
839
840 Buffer - Buffe to print Guid into.
841
842 BufferSize - Size of Buffer.
843
844 Returns:
845
846 Number of characters printed.
847
848 --*/
849 {
850 UINTN Size;
851
852 Size = SPrint (
853 Buffer,
854 BufferSize,
855 STRING_W ("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"),
856 (UINTN)Guid->Data1,
857 (UINTN)Guid->Data2,
858 (UINTN)Guid->Data3,
859 (UINTN)Guid->Data4[0],
860 (UINTN)Guid->Data4[1],
861 (UINTN)Guid->Data4[2],
862 (UINTN)Guid->Data4[3],
863 (UINTN)Guid->Data4[4],
864 (UINTN)Guid->Data4[5],
865 (UINTN)Guid->Data4[6],
866 (UINTN)Guid->Data4[7]
867 );
868
869 //
870 // SPrint will null terminate the string. The -1 skips the null
871 //
872 return Size - 1;
873 }
874
875
876 STATIC
877 UINTN
878 TimeToString (
879 IN EFI_TIME *Time,
880 OUT CHAR_W *Buffer,
881 IN UINTN BufferSize
882 )
883 /*++
884
885 Routine Description:
886
887 VSPrint worker function that prints EFI_TIME.
888
889 Arguments:
890
891 Time - Pointer to EFI_TIME sturcture to print.
892
893 Buffer - Buffer to print Time into.
894
895 BufferSize - Size of Buffer.
896
897 Returns:
898
899 Number of characters printed.
900
901 --*/
902 {
903 UINTN Size;
904
905 Size = SPrint (
906 Buffer,
907 BufferSize,
908 STRING_W ("%02d/%02d/%04d %02d:%02d"),
909 (UINTN)Time->Month,
910 (UINTN)Time->Day,
911 (UINTN)Time->Year,
912 (UINTN)Time->Hour,
913 (UINTN)Time->Minute
914 );
915
916 //
917 // SPrint will null terminate the string. The -1 skips the null
918 //
919 return Size - 1;
920 }
921
922 STATIC
923 UINTN
924 EfiStatusToString (
925 IN EFI_STATUS Status,
926 OUT CHAR_W *Buffer,
927 IN UINTN BufferSize
928 )
929 /*++
930
931 Routine Description:
932
933 VSPrint worker function that prints EFI_STATUS as a string. If string is
934 not known a hex value will be printed.
935
936 Arguments:
937
938 Status - EFI_STATUS sturcture to print.
939
940 Buffer - Buffer to print EFI_STATUS message string into.
941
942 BufferSize - Size of Buffer.
943
944 Returns:
945
946 Number of characters printed.
947
948 --*/
949 {
950 UINTN Size;
951 CHAR8 *Desc;
952
953 Desc = NULL;
954
955 //
956 // Can't use global Status String Array as UINTN is not constant for EBC
957 //
958 if (Status == EFI_SUCCESS) { Desc = (CHAR8 *) "Success"; } else
959 if (Status == EFI_LOAD_ERROR) { Desc = (CHAR8 *) "Load Error"; } else
960 if (Status == EFI_INVALID_PARAMETER) { Desc = (CHAR8 *) "Invalid Parameter"; } else
961 if (Status == EFI_UNSUPPORTED) { Desc = (CHAR8 *) "Unsupported"; } else
962 if (Status == EFI_BAD_BUFFER_SIZE) { Desc = (CHAR8 *) "Bad Buffer Size"; } else
963 if (Status == EFI_BUFFER_TOO_SMALL) { Desc = (CHAR8 *) "Buffer Too Small"; } else
964 if (Status == EFI_NOT_READY) { Desc = (CHAR8 *) "Not Ready"; } else
965 if (Status == EFI_DEVICE_ERROR) { Desc = (CHAR8 *) "Device Error"; } else
966 if (Status == EFI_WRITE_PROTECTED) { Desc = (CHAR8 *) "Write Protected"; } else
967 if (Status == EFI_OUT_OF_RESOURCES) { Desc = (CHAR8 *) "Out of Resources"; } else
968 if (Status == EFI_VOLUME_CORRUPTED) { Desc = (CHAR8 *) "Volume Corrupt"; } else
969 if (Status == EFI_VOLUME_FULL) { Desc = (CHAR8 *) "Volume Full"; } else
970 if (Status == EFI_NO_MEDIA) { Desc = (CHAR8 *) "No Media"; } else
971 if (Status == EFI_MEDIA_CHANGED) { Desc = (CHAR8 *) "Media changed"; } else
972 if (Status == EFI_NOT_FOUND) { Desc = (CHAR8 *) "Not Found"; } else
973 if (Status == EFI_ACCESS_DENIED) { Desc = (CHAR8 *) "Access Denied"; } else
974 if (Status == EFI_NO_RESPONSE) { Desc = (CHAR8 *) "No Response"; } else
975 if (Status == EFI_NO_MAPPING) { Desc = (CHAR8 *) "No mapping"; } else
976 if (Status == EFI_TIMEOUT) { Desc = (CHAR8 *) "Time out"; } else
977 if (Status == EFI_NOT_STARTED) { Desc = (CHAR8 *) "Not started"; } else
978 if (Status == EFI_ALREADY_STARTED) { Desc = (CHAR8 *) "Already started"; } else
979 if (Status == EFI_ABORTED) { Desc = (CHAR8 *) "Aborted"; } else
980 if (Status == EFI_ICMP_ERROR) { Desc = (CHAR8 *) "ICMP Error"; } else
981 if (Status == EFI_TFTP_ERROR) { Desc = (CHAR8 *) "TFTP Error"; } else
982 if (Status == EFI_PROTOCOL_ERROR) { Desc = (CHAR8 *) "Protocol Error"; } else
983 if (Status == EFI_WARN_UNKNOWN_GLYPH) { Desc = (CHAR8 *) "Warning Unknown Glyph"; } else
984 if (Status == EFI_WARN_DELETE_FAILURE) { Desc = (CHAR8 *) "Warning Delete Failure"; } else
985 if (Status == EFI_WARN_WRITE_FAILURE) { Desc = (CHAR8 *) "Warning Write Failure"; } else
986 if (Status == EFI_WARN_BUFFER_TOO_SMALL) { Desc = (CHAR8 *) "Warning Buffer Too Small"; }
987
988 //
989 // If we found a match, copy the message to the user's buffer. Otherwise
990 // sprint the hex status code to their buffer.
991 //
992 if (Desc != NULL) {
993 Size = SPrint (Buffer, BufferSize, STRING_W ("%a"), Desc);
994 } else {
995 Size = SPrint (Buffer, BufferSize, STRING_W ("%X"), Status);
996 }
997
998 return Size - 1;
999 }