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