Home | History | Annotate | Download | only in Graphics
      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