1 /*++ 2 3 Copyright (c) 2004 - 2012, 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 69 STATIC 70 UINTN 71 GuidToString ( 72 IN EFI_GUID *Guid, 73 IN OUT CHAR_W *Buffer, 74 IN UINTN BufferSize 75 ); 76 77 STATIC 78 UINTN 79 TimeToString ( 80 IN EFI_TIME *Time, 81 IN OUT CHAR_W *Buffer, 82 IN UINTN BufferSize 83 ); 84 85 STATIC 86 UINTN 87 EfiStatusToString ( 88 IN EFI_STATUS Status, 89 OUT CHAR_W *Buffer, 90 IN UINTN BufferSize 91 ); 92 93 static 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 113 UINTN 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 127 Routine Description: 128 129 Display string worker for: Print, PrintAt, IPrint, IPrintAt 130 131 Arguments: 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 151 Returns: 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 361 Error: 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 378 UINTN 379 PrintXY ( 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 389 Routine Description: 390 391 Prints a formatted unicode string to the default console 392 393 Arguments: 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 407 Returns: 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 463 UINTN 464 SPrint ( 465 OUT CHAR_W *Buffer, 466 IN UINTN BufferSize, 467 IN CONST CHAR_W *Format, 468 ... 469 ) 470 /*++ 471 472 Routine Description: 473 474 SPrint function to process format and place the results in Buffer. 475 476 Arguments: 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 487 Returns: 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 503 UINTN 504 EFIAPI 505 VSPrint ( 506 OUT CHAR_W *StartOfBuffer, 507 IN UINTN BufferSize, 508 IN CONST CHAR_W *FormatString, 509 IN VA_LIST Marker 510 ) 511 /*++ 512 513 Routine 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 519 Arguments: 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 530 Returns: 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 780 STATIC 781 UINTN 782 GuidToString ( 783 IN EFI_GUID *Guid, 784 IN CHAR_W *Buffer, 785 IN UINTN BufferSize 786 ) 787 /*++ 788 789 Routine Description: 790 791 VSPrint worker function that prints an EFI_GUID. 792 793 Arguments: 794 795 Guid - Pointer to GUID to print. 796 797 Buffer - Buffe to print Guid into. 798 799 BufferSize - Size of Buffer. 800 801 Returns: 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 833 STATIC 834 UINTN 835 TimeToString ( 836 IN EFI_TIME *Time, 837 OUT CHAR_W *Buffer, 838 IN UINTN BufferSize 839 ) 840 /*++ 841 842 Routine Description: 843 844 VSPrint worker function that prints EFI_TIME. 845 846 Arguments: 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 854 Returns: 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 879 STATIC 880 UINTN 881 EfiStatusToString ( 882 IN EFI_STATUS Status, 883 OUT CHAR_W *Buffer, 884 IN UINTN BufferSize 885 ) 886 /*++ 887 888 Routine 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 893 Arguments: 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 901 Returns: 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