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