Home | History | Annotate | Download | only in DxePrintLibPrint2Protocol
      1 /** @file
      2   Instance of Print Library based on gEfiPrint2ProtocolGuid.
      3 
      4   Implement the print library instance by wrap the interface
      5   provided in the Print2 protocol. This protocol is defined as the internal
      6   protocol related to this implementation, not in the public spec. So, this
      7   library instance is only for this code base.
      8 
      9 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
     10 This program and the accompanying materials
     11 are licensed and made available under the terms and conditions of the BSD License
     12 which accompanies this distribution.  The full text of the license may be found at
     13 http://opensource.org/licenses/bsd-license.php
     14 
     15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     16 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     17 
     18 **/
     19 
     20 #include <Uefi.h>
     21 #include <Base.h>
     22 #include <Protocol/Print2.h>
     23 
     24 #include <Library/PrintLib.h>
     25 
     26 #include <Library/BaseLib.h>
     27 #include <Library/DebugLib.h>
     28 
     29 EFI_PRINT2_PROTOCOL  *mPrint2Protocol = NULL;
     30 
     31 /**
     32   The constructor function caches the pointer to Print2 protocol.
     33 
     34   The constructor function locates Print2 protocol from protocol database.
     35   It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.
     36 
     37   @param  ImageHandle   The firmware allocated handle for the EFI image.
     38   @param  SystemTable   A pointer to the EFI System Table.
     39 
     40   @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
     41 
     42 **/
     43 EFI_STATUS
     44 EFIAPI
     45 PrintLibConstructor (
     46   IN EFI_HANDLE                ImageHandle,
     47   IN EFI_SYSTEM_TABLE          *SystemTable
     48   )
     49 {
     50   EFI_STATUS                   Status;
     51 
     52   Status = SystemTable->BootServices->LocateProtocol (
     53                                         &gEfiPrint2ProtocolGuid,
     54                                         NULL,
     55                                         (VOID**) &mPrint2Protocol
     56                                         );
     57   ASSERT_EFI_ERROR (Status);
     58   ASSERT (mPrint2Protocol != NULL);
     59 
     60   return Status;
     61 }
     62 
     63 
     64 /**
     65   Worker function that converts a VA_LIST to a BASE_LIST based on a Null-terminated
     66   format string.
     67 
     68   @param  AsciiFormat     TRUE if Format is an ASCII string.  FALSE if Format is a Unicode string.
     69   @param  Format          Null-terminated format string.
     70   @param  VaListMarker    VA_LIST style variable argument list consumed by processing Format.
     71   @param  BaseListMarker  BASE_LIST style variable argument list consumed by processing Format.
     72   @param  Size            The size, in bytes, of the BaseListMarker buffer.
     73 
     74   @return The number of bytes in BaseListMarker.  0 if BaseListMarker is too small.
     75 
     76 **/
     77 BOOLEAN
     78 DxePrintLibPrint2ProtocolVaListToBaseList (
     79   IN  BOOLEAN      AsciiFormat,
     80   IN  CONST CHAR8  *Format,
     81   IN  VA_LIST      VaListMarker,
     82   OUT BASE_LIST    BaseListMarker,
     83   IN  UINTN        Size
     84   )
     85 {
     86   BASE_LIST  BaseListStart;
     87   UINTN      BytesPerFormatCharacter;
     88   UINTN      FormatMask;
     89   UINTN      FormatCharacter;
     90   BOOLEAN    Long;
     91   BOOLEAN    Done;
     92 
     93   ASSERT (Format         != NULL);
     94   ASSERT (BaseListMarker != NULL);
     95 
     96   BaseListStart = BaseListMarker;
     97 
     98   if (AsciiFormat) {
     99     ASSERT (AsciiStrSize (Format) != 0);
    100     BytesPerFormatCharacter = 1;
    101     FormatMask = 0xff;
    102   } else {
    103     ASSERT (StrSize ((CHAR16 *) Format) != 0);
    104     BytesPerFormatCharacter = 2;
    105     FormatMask = 0xffff;
    106   }
    107 
    108   //
    109   // Get the first character from the format string
    110   //
    111   FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
    112 
    113   while (FormatCharacter != 0) {
    114     if (FormatCharacter == '%') {
    115       Long = FALSE;
    116 
    117       //
    118       // Parse Flags and Width
    119       //
    120       for (Done = FALSE; !Done; ) {
    121         //
    122         // Get the next character from the format string
    123         //
    124         Format += BytesPerFormatCharacter;
    125 
    126         //
    127         // Get the next character from the format string
    128         //
    129         FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
    130 
    131         switch (FormatCharacter) {
    132         case '.':
    133         case '-':
    134         case '+':
    135         case ' ':
    136         case ',':
    137         case '0':
    138         case '1':
    139         case '2':
    140         case '3':
    141         case '4':
    142         case '5':
    143         case '6':
    144         case '7':
    145         case '8':
    146         case '9':
    147           break;
    148         case 'L':
    149         case 'l':
    150           Long = TRUE;
    151           break;
    152         case '*':
    153           BASE_ARG (BaseListMarker, UINTN) = VA_ARG (VaListMarker, UINTN);
    154           break;
    155         case '\0':
    156           //
    157           // Make no output if Format string terminates unexpectedly when
    158           // looking up for flag, width, precision and type.
    159           //
    160           Format -= BytesPerFormatCharacter;
    161           //
    162           // break skipped on purpose.
    163           //
    164         default:
    165           Done = TRUE;
    166           break;
    167         }
    168       }
    169 
    170       //
    171       // Handle each argument type
    172       //
    173       switch (FormatCharacter) {
    174       case 'p':
    175         if (sizeof (VOID *) > 4) {
    176           Long = TRUE;
    177         }
    178       case 'X':
    179       case 'x':
    180       case 'u':
    181       case 'd':
    182         if (Long) {
    183           BASE_ARG (BaseListMarker, INT64) = VA_ARG (VaListMarker, INT64);
    184         } else {
    185           BASE_ARG (BaseListMarker, int) = VA_ARG (VaListMarker, int);
    186         }
    187         break;
    188       case 's':
    189       case 'S':
    190       case 'a':
    191       case 'g':
    192       case 't':
    193         BASE_ARG (BaseListMarker, VOID *) = VA_ARG (VaListMarker, VOID *);
    194         break;
    195       case 'c':
    196         BASE_ARG (BaseListMarker, UINTN) = VA_ARG (VaListMarker, UINTN);
    197         break;
    198       case 'r':
    199         BASE_ARG (BaseListMarker, RETURN_STATUS) = VA_ARG (VaListMarker, RETURN_STATUS);
    200         break;
    201       }
    202     }
    203 
    204     //
    205     // If BASE_LIST is larger than Size, then return FALSE
    206     //
    207     if ((UINTN)((UINT8 *)BaseListMarker - (UINT8 *)BaseListStart) > Size) {
    208       return FALSE;
    209     }
    210 
    211     //
    212     // Get the next character from the format string
    213     //
    214     Format += BytesPerFormatCharacter;
    215 
    216     //
    217     // Get the next character from the format string
    218     //
    219     FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
    220   }
    221   return TRUE;
    222 }
    223 
    224 /**
    225   Produces a Null-terminated Unicode string in an output buffer based on
    226   a Null-terminated Unicode format string and a VA_LIST argument list
    227 
    228   Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer
    229   and BufferSize.
    230   The Unicode string is produced by parsing the format string specified by FormatString.
    231   Arguments are pulled from the variable argument list specified by Marker based on the
    232   contents of the format string.
    233   The number of Unicode characters in the produced output buffer is returned not including
    234   the Null-terminator.
    235   If BufferSize is 0 or 1, then no output buffer is produced and 0 is returned.
    236 
    237   If BufferSize > 1 and StartOfBuffer is NULL, then ASSERT().
    238   If BufferSize > 1 and StartOfBuffer is not aligned on a 16-bit boundary, then ASSERT().
    239   If BufferSize > 1 and FormatString is NULL, then ASSERT().
    240   If BufferSize > 1 and FormatString is not aligned on a 16-bit boundary, then ASSERT().
    241   If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than
    242   PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, then
    243   ASSERT().
    244   If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string
    245   contains more than PcdMaximumUnicodeStringLength Unicode characters not including the
    246   Null-terminator, then ASSERT().
    247 
    248   @param  StartOfBuffer   A pointer to the output buffer for the produced Null-terminated
    249                           Unicode string.
    250   @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.
    251   @param  FormatString    Null-terminated Unicode format string.
    252   @param  Marker          VA_LIST marker for the variable argument list.
    253 
    254   @return The number of Unicode characters in the produced output buffer not including the
    255           Null-terminator.
    256 
    257 **/
    258 UINTN
    259 EFIAPI
    260 UnicodeVSPrint (
    261   OUT CHAR16        *StartOfBuffer,
    262   IN  UINTN         BufferSize,
    263   IN  CONST CHAR16  *FormatString,
    264   IN  VA_LIST       Marker
    265   )
    266 {
    267   UINT64  BaseListMarker[256 / sizeof (UINT64)];
    268 
    269   DxePrintLibPrint2ProtocolVaListToBaseList (
    270     FALSE,
    271     (CHAR8 *)FormatString,
    272     Marker,
    273     (BASE_LIST)BaseListMarker,
    274     sizeof (BaseListMarker) - 8
    275     );
    276 
    277   return UnicodeBSPrint (StartOfBuffer, BufferSize, FormatString, (BASE_LIST)BaseListMarker);
    278 }
    279 
    280 /**
    281   Produces a Null-terminated Unicode string in an output buffer based on
    282   a Null-terminated Unicode format string and a BASE_LIST argument list
    283 
    284   Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer
    285   and BufferSize.
    286   The Unicode string is produced by parsing the format string specified by FormatString.
    287   Arguments are pulled from the variable argument list specified by Marker based on the
    288   contents of the format string.
    289   The number of Unicode characters in the produced output buffer is returned not including
    290   the Null-terminator.
    291   If BufferSize is 0 or 1, then no output buffer is produced and 0 is returned.
    292 
    293   If BufferSize > 1 and StartOfBuffer is NULL, then ASSERT().
    294   If BufferSize > 1 and StartOfBuffer is not aligned on a 16-bit boundary, then ASSERT().
    295   If BufferSize > 1 and FormatString is NULL, then ASSERT().
    296   If BufferSize > 1 and FormatString is not aligned on a 16-bit boundary, then ASSERT().
    297   If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than
    298   PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, then
    299   ASSERT().
    300   If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string
    301   contains more than PcdMaximumUnicodeStringLength Unicode characters not including the
    302   Null-terminator, then ASSERT().
    303 
    304   @param  StartOfBuffer   A pointer to the output buffer for the produced Null-terminated
    305                           Unicode string.
    306   @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.
    307   @param  FormatString    Null-terminated Unicode format string.
    308   @param  Marker          BASE_LIST marker for the variable argument list.
    309 
    310   @return The number of Unicode characters in the produced output buffer not including the
    311           Null-terminator.
    312 
    313 **/
    314 UINTN
    315 EFIAPI
    316 UnicodeBSPrint (
    317   OUT CHAR16        *StartOfBuffer,
    318   IN  UINTN         BufferSize,
    319   IN  CONST CHAR16  *FormatString,
    320   IN  BASE_LIST     Marker
    321   )
    322 {
    323   return mPrint2Protocol->UnicodeBSPrint (StartOfBuffer, BufferSize, FormatString, Marker);
    324 }
    325 
    326 /**
    327   Produces a Null-terminated Unicode string in an output buffer based on a Null-terminated
    328   Unicode format string and variable argument list.
    329 
    330   Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer
    331   and BufferSize.
    332   The Unicode string is produced by parsing the format string specified by FormatString.
    333   Arguments are pulled from the variable argument list based on the contents of the format string.
    334   The number of Unicode characters in the produced output buffer is returned not including
    335   the Null-terminator.
    336   If BufferSize is 0 or 1, then no output buffer is produced and 0 is returned.
    337 
    338   If BufferSize > 1 and StartOfBuffer is NULL, then ASSERT().
    339   If BufferSize > 1 and StartOfBuffer is not aligned on a 16-bit boundary, then ASSERT().
    340   If BufferSize > 1 and FormatString is NULL, then ASSERT().
    341   If BufferSize > 1 and FormatString is not aligned on a 16-bit boundary, then ASSERT().
    342   If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than
    343   PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, then
    344   ASSERT().
    345   If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string
    346   contains more than PcdMaximumUnicodeStringLength Unicode characters not including the
    347   Null-terminator, then ASSERT().
    348 
    349   @param  StartOfBuffer   A pointer to the output buffer for the produced Null-terminated
    350                           Unicode string.
    351   @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.
    352   @param  FormatString    Null-terminated Unicode format string.
    353   @param  ...             Variable argument list whose contents are accessed based on the
    354                           format string specified by FormatString.
    355 
    356   @return The number of Unicode characters in the produced output buffer not including the
    357           Null-terminator.
    358 
    359 **/
    360 UINTN
    361 EFIAPI
    362 UnicodeSPrint (
    363   OUT CHAR16        *StartOfBuffer,
    364   IN  UINTN         BufferSize,
    365   IN  CONST CHAR16  *FormatString,
    366   ...
    367   )
    368 {
    369   VA_LIST Marker;
    370   UINTN   NumberOfPrinted;
    371 
    372   VA_START (Marker, FormatString);
    373   NumberOfPrinted = UnicodeVSPrint (StartOfBuffer, BufferSize, FormatString, Marker);
    374   VA_END (Marker);
    375   return NumberOfPrinted;
    376 }
    377 
    378 /**
    379   Produces a Null-terminated Unicode string in an output buffer based on a Null-terminated
    380   ASCII format string and a VA_LIST argument list
    381 
    382   Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer
    383   and BufferSize.
    384   The Unicode string is produced by parsing the format string specified by FormatString.
    385   Arguments are pulled from the variable argument list specified by Marker based on the
    386   contents of the format string.
    387   The number of Unicode characters in the produced output buffer is returned not including
    388   the Null-terminator.
    389   If BufferSize is 0 or 1, then no output buffer is produced and 0 is returned.
    390 
    391   If BufferSize > 1 and StartOfBuffer is NULL, then ASSERT().
    392   If BufferSize > 1 and StartOfBuffer is not aligned on a 16-bit boundary, then ASSERT().
    393   If BufferSize > 1 and FormatString is NULL, then ASSERT().
    394   If PcdMaximumAsciiStringLength is not zero, and FormatString contains more than
    395   PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, then
    396   ASSERT().
    397   If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string
    398   contains more than PcdMaximumUnicodeStringLength Unicode characters not including the
    399   Null-terminator, then ASSERT().
    400 
    401   @param  StartOfBuffer   A pointer to the output buffer for the produced Null-terminated
    402                           Unicode string.
    403   @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.
    404   @param  FormatString    Null-terminated Unicode format string.
    405   @param  Marker          VA_LIST marker for the variable argument list.
    406 
    407   @return The number of Unicode characters in the produced output buffer not including the
    408           Null-terminator.
    409 
    410 **/
    411 UINTN
    412 EFIAPI
    413 UnicodeVSPrintAsciiFormat (
    414   OUT CHAR16       *StartOfBuffer,
    415   IN  UINTN        BufferSize,
    416   IN  CONST CHAR8  *FormatString,
    417   IN  VA_LIST      Marker
    418   )
    419 {
    420   UINT64  BaseListMarker[256 / sizeof (UINT64)];
    421 
    422   DxePrintLibPrint2ProtocolVaListToBaseList (
    423     TRUE,
    424     FormatString,
    425     Marker,
    426     (BASE_LIST)BaseListMarker,
    427     sizeof (BaseListMarker) - 8
    428     );
    429 
    430   return UnicodeBSPrintAsciiFormat (StartOfBuffer, BufferSize, FormatString, (BASE_LIST)BaseListMarker);
    431 }
    432 
    433 /**
    434   Produces a Null-terminated Unicode string in an output buffer based on a Null-terminated
    435   ASCII format string and a BASE_LIST argument list
    436 
    437   Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer
    438   and BufferSize.
    439   The Unicode string is produced by parsing the format string specified by FormatString.
    440   Arguments are pulled from the variable argument list specified by Marker based on the
    441   contents of the format string.
    442   The number of Unicode characters in the produced output buffer is returned not including
    443   the Null-terminator.
    444   If BufferSize is 0 or 1, then no output buffer is produced and 0 is returned.
    445 
    446   If BufferSize > 1 and StartOfBuffer is NULL, then ASSERT().
    447   If BufferSize > 1 and StartOfBuffer is not aligned on a 16-bit boundary, then ASSERT().
    448   If BufferSize > 1 and FormatString is NULL, then ASSERT().
    449   If PcdMaximumAsciiStringLength is not zero, and FormatString contains more than
    450   PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, then
    451   ASSERT().
    452   If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string
    453   contains more than PcdMaximumUnicodeStringLength Unicode characters not including the
    454   Null-terminator, then ASSERT().
    455 
    456   @param  StartOfBuffer   A pointer to the output buffer for the produced Null-terminated
    457                           Unicode string.
    458   @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.
    459   @param  FormatString    Null-terminated Unicode format string.
    460   @param  Marker          BASE_LIST marker for the variable argument list.
    461 
    462   @return The number of Unicode characters in the produced output buffer not including the
    463           Null-terminator.
    464 
    465 **/
    466 UINTN
    467 EFIAPI
    468 UnicodeBSPrintAsciiFormat (
    469   OUT CHAR16       *StartOfBuffer,
    470   IN  UINTN        BufferSize,
    471   IN  CONST CHAR8  *FormatString,
    472   IN  BASE_LIST    Marker
    473   )
    474 {
    475   return mPrint2Protocol->UnicodeBSPrintAsciiFormat (StartOfBuffer, BufferSize, FormatString, Marker);
    476 }
    477 
    478 /**
    479   Produces a Null-terminated Unicode string in an output buffer based on a Null-terminated
    480   ASCII format string and  variable argument list.
    481 
    482   Produces a Null-terminated Unicode string in the output buffer specified by StartOfBuffer
    483   and BufferSize.
    484   The Unicode string is produced by parsing the format string specified by FormatString.
    485   Arguments are pulled from the variable argument list based on the contents of the
    486   format string.
    487   The number of Unicode characters in the produced output buffer is returned not including
    488   the Null-terminator.
    489   If BufferSize is 0 or 1, then no output buffer is produced and 0 is returned.
    490 
    491   If BufferSize > 1 and StartOfBuffer is NULL, then ASSERT().
    492   If BufferSize > 1 and StartOfBuffer is not aligned on a 16-bit boundary, then ASSERT().
    493   If BufferSize > 1 and FormatString is NULL, then ASSERT().
    494   If PcdMaximumAsciiStringLength is not zero, and FormatString contains more than
    495   PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, then
    496   ASSERT().
    497   If PcdMaximumUnicodeStringLength is not zero, and produced Null-terminated Unicode string
    498   contains more than PcdMaximumUnicodeStringLength Unicode characters not including the
    499   Null-terminator, then ASSERT().
    500 
    501   @param  StartOfBuffer   A pointer to the output buffer for the produced Null-terminated
    502                           Unicode string.
    503   @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.
    504   @param  FormatString    Null-terminated Unicode format string.
    505   @param  ...             Variable argument list whose contents are accessed based on the
    506                           format string specified by FormatString.
    507 
    508   @return The number of Unicode characters in the produced output buffer not including the
    509           Null-terminator.
    510 
    511 **/
    512 UINTN
    513 EFIAPI
    514 UnicodeSPrintAsciiFormat (
    515   OUT CHAR16       *StartOfBuffer,
    516   IN  UINTN        BufferSize,
    517   IN  CONST CHAR8  *FormatString,
    518   ...
    519   )
    520 {
    521   VA_LIST Marker;
    522   UINTN   NumberOfPrinted;
    523 
    524   VA_START (Marker, FormatString);
    525   NumberOfPrinted = UnicodeVSPrintAsciiFormat (StartOfBuffer, BufferSize, FormatString, Marker);
    526   VA_END (Marker);
    527   return NumberOfPrinted;
    528 }
    529 
    530 /**
    531   Converts a decimal value to a Null-terminated Unicode string.
    532 
    533   Converts the decimal number specified by Value to a Null-terminated Unicode
    534   string specified by Buffer containing at most Width characters. No padding of spaces
    535   is ever performed. If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
    536   The number of Unicode characters in Buffer is returned not including the Null-terminator.
    537   If the conversion contains more than Width characters, then only the first
    538   Width characters are returned, and the total number of characters
    539   required to perform the conversion is returned.
    540   Additional conversion parameters are specified in Flags.
    541 
    542   The Flags bit LEFT_JUSTIFY is always ignored.
    543   All conversions are left justified in Buffer.
    544   If Width is 0, PREFIX_ZERO is ignored in Flags.
    545   If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas
    546   are inserted every 3rd digit starting from the right.
    547   If RADIX_HEX is set in Flags, then the output buffer will be
    548   formatted in hexadecimal format.
    549   If Value is < 0 and RADIX_HEX is not set in Flags, then the fist character in Buffer is a '-'.
    550   If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,
    551   then Buffer is padded with '0' characters so the combination of the optional '-'
    552   sign character, '0' characters, digit characters for Value, and the Null-terminator
    553   add up to Width characters.
    554   If both COMMA_TYPE and RADIX_HEX are set in Flags, then ASSERT().
    555   If Buffer is NULL, then ASSERT().
    556   If Buffer is not aligned on a 16-bit boundary, then ASSERT().
    557   If unsupported bits are set in Flags, then ASSERT().
    558   If both COMMA_TYPE and RADIX_HEX are set in Flags, then ASSERT().
    559   If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()
    560 
    561   @param  Buffer  Pointer to the output buffer for the produced Null-terminated
    562                   Unicode string.
    563   @param  Flags   The bitmask of flags that specify left justification, zero pad, and commas.
    564   @param  Value   The 64-bit signed value to convert to a string.
    565   @param  Width   The maximum number of Unicode characters to place in Buffer, not including
    566                   the Null-terminator.
    567 
    568   @return The number of Unicode characters in Buffer not including the Null-terminator.
    569 
    570 **/
    571 UINTN
    572 EFIAPI
    573 UnicodeValueToString (
    574   IN OUT CHAR16  *Buffer,
    575   IN UINTN       Flags,
    576   IN INT64       Value,
    577   IN UINTN       Width
    578   )
    579 {
    580   return mPrint2Protocol->UnicodeValueToString (Buffer, Flags, Value, Width);
    581 }
    582 
    583 /**
    584   Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated
    585   ASCII format string and a VA_LIST argument list.
    586 
    587   Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer
    588   and BufferSize.
    589   The ASCII string is produced by parsing the format string specified by FormatString.
    590   Arguments are pulled from the variable argument list specified by Marker based on
    591   the contents of the format string.
    592   The number of ASCII characters in the produced output buffer is returned not including
    593   the Null-terminator.
    594   If BufferSize is 0, then no output buffer is produced and 0 is returned.
    595 
    596   If BufferSize > 0 and StartOfBuffer is NULL, then ASSERT().
    597   If BufferSize > 0 and FormatString is NULL, then ASSERT().
    598   If PcdMaximumAsciiStringLength is not zero, and FormatString contains more than
    599   PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, then
    600   ASSERT().
    601   If PcdMaximumAsciiStringLength is not zero, and produced Null-terminated ASCII string
    602   contains more than PcdMaximumAsciiStringLength ASCII characters not including the
    603   Null-terminator, then ASSERT().
    604 
    605   @param  StartOfBuffer   A pointer to the output buffer for the produced Null-terminated
    606                           ASCII string.
    607   @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.
    608   @param  FormatString    Null-terminated Unicode format string.
    609   @param  Marker          VA_LIST marker for the variable argument list.
    610 
    611   @return The number of ASCII characters in the produced output buffer not including the
    612           Null-terminator.
    613 
    614 **/
    615 UINTN
    616 EFIAPI
    617 AsciiVSPrint (
    618   OUT CHAR8         *StartOfBuffer,
    619   IN  UINTN         BufferSize,
    620   IN  CONST CHAR8   *FormatString,
    621   IN  VA_LIST       Marker
    622   )
    623 {
    624   UINT64  BaseListMarker[256 / sizeof (UINT64)];
    625 
    626   DxePrintLibPrint2ProtocolVaListToBaseList (
    627     TRUE,
    628     FormatString,
    629     Marker,
    630     (BASE_LIST)BaseListMarker,
    631     sizeof (BaseListMarker) - 8
    632     );
    633 
    634   return AsciiBSPrint (StartOfBuffer, BufferSize, FormatString, (BASE_LIST)BaseListMarker);
    635 }
    636 
    637 /**
    638   Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated
    639   ASCII format string and a BASE_LIST argument list.
    640 
    641   Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer
    642   and BufferSize.
    643   The ASCII string is produced by parsing the format string specified by FormatString.
    644   Arguments are pulled from the variable argument list specified by Marker based on
    645   the contents of the format string.
    646   The number of ASCII characters in the produced output buffer is returned not including
    647   the Null-terminator.
    648   If BufferSize is 0, then no output buffer is produced and 0 is returned.
    649 
    650   If BufferSize > 0 and StartOfBuffer is NULL, then ASSERT().
    651   If BufferSize > 0 and FormatString is NULL, then ASSERT().
    652   If PcdMaximumAsciiStringLength is not zero, and FormatString contains more than
    653   PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, then
    654   ASSERT().
    655   If PcdMaximumAsciiStringLength is not zero, and produced Null-terminated ASCII string
    656   contains more than PcdMaximumAsciiStringLength ASCII characters not including the
    657   Null-terminator, then ASSERT().
    658 
    659   @param  StartOfBuffer   A pointer to the output buffer for the produced Null-terminated
    660                           ASCII string.
    661   @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.
    662   @param  FormatString    Null-terminated Unicode format string.
    663   @param  Marker          BASE_LIST marker for the variable argument list.
    664 
    665   @return The number of ASCII characters in the produced output buffer not including the
    666           Null-terminator.
    667 
    668 **/
    669 UINTN
    670 EFIAPI
    671 AsciiBSPrint (
    672   OUT CHAR8         *StartOfBuffer,
    673   IN  UINTN         BufferSize,
    674   IN  CONST CHAR8   *FormatString,
    675   IN  BASE_LIST     Marker
    676   )
    677 {
    678   return mPrint2Protocol->AsciiBSPrint (StartOfBuffer, BufferSize, FormatString, Marker);
    679 }
    680 
    681 /**
    682   Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated
    683   ASCII format string and  variable argument list.
    684 
    685   Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer
    686   and BufferSize.
    687   The ASCII string is produced by parsing the format string specified by FormatString.
    688   Arguments are pulled from the variable argument list based on the contents of the
    689   format string.
    690   The number of ASCII characters in the produced output buffer is returned not including
    691   the Null-terminator.
    692   If BufferSize is 0, then no output buffer is produced and 0 is returned.
    693 
    694   If BufferSize > 0 and StartOfBuffer is NULL, then ASSERT().
    695   If BufferSize > 0 and FormatString is NULL, then ASSERT().
    696   If PcdMaximumAsciiStringLength is not zero, and FormatString contains more than
    697   PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, then
    698   ASSERT().
    699   If PcdMaximumAsciiStringLength is not zero, and produced Null-terminated ASCII string
    700   contains more than PcdMaximumAsciiStringLength ASCII characters not including the
    701   Null-terminator, then ASSERT().
    702 
    703   @param  StartOfBuffer   A pointer to the output buffer for the produced Null-terminated
    704                           ASCII string.
    705   @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.
    706   @param  FormatString    Null-terminated Unicode format string.
    707   @param  ...             Variable argument list whose contents are accessed based on the
    708                           format string specified by FormatString.
    709 
    710   @return The number of ASCII characters in the produced output buffer not including the
    711           Null-terminator.
    712 
    713 **/
    714 UINTN
    715 EFIAPI
    716 AsciiSPrint (
    717   OUT CHAR8        *StartOfBuffer,
    718   IN  UINTN        BufferSize,
    719   IN  CONST CHAR8  *FormatString,
    720   ...
    721   )
    722 {
    723   VA_LIST Marker;
    724   UINTN   NumberOfPrinted;
    725 
    726   VA_START (Marker, FormatString);
    727   NumberOfPrinted = AsciiVSPrint (StartOfBuffer, BufferSize, FormatString, Marker);
    728   VA_END (Marker);
    729   return NumberOfPrinted;
    730 }
    731 
    732 /**
    733   Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated
    734   ASCII format string and a VA_LIST argument list.
    735 
    736   Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer
    737   and BufferSize.
    738   The ASCII string is produced by parsing the format string specified by FormatString.
    739   Arguments are pulled from the variable argument list specified by Marker based on
    740   the contents of the format string.
    741   The number of ASCII characters in the produced output buffer is returned not including
    742   the Null-terminator.
    743   If BufferSize is 0, then no output buffer is produced and 0 is returned.
    744 
    745   If BufferSize > 0 and StartOfBuffer is NULL, then ASSERT().
    746   If BufferSize > 0 and FormatString is NULL, then ASSERT().
    747   If BufferSize > 0 and FormatString is not aligned on a 16-bit boundary, then ASSERT().
    748   If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than
    749   PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, then
    750   ASSERT().
    751   If PcdMaximumAsciiStringLength is not zero, and produced Null-terminated ASCII string
    752   contains more than PcdMaximumAsciiStringLength ASCII characters not including the
    753   Null-terminator, then ASSERT().
    754 
    755   @param  StartOfBuffer   A pointer to the output buffer for the produced Null-terminated
    756                           ASCII string.
    757   @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.
    758   @param  FormatString    Null-terminated Unicode format string.
    759   @param  Marker          VA_LIST marker for the variable argument list.
    760 
    761   @return The number of ASCII characters in the produced output buffer not including the
    762           Null-terminator.
    763 
    764 **/
    765 UINTN
    766 EFIAPI
    767 AsciiVSPrintUnicodeFormat (
    768   OUT CHAR8         *StartOfBuffer,
    769   IN  UINTN         BufferSize,
    770   IN  CONST CHAR16  *FormatString,
    771   IN  VA_LIST       Marker
    772   )
    773 {
    774   UINT64  BaseListMarker[256 / sizeof (UINT64)];
    775 
    776   DxePrintLibPrint2ProtocolVaListToBaseList (
    777     FALSE,
    778     (CHAR8 *)FormatString,
    779     Marker,
    780     (BASE_LIST)BaseListMarker,
    781     sizeof (BaseListMarker) - 8
    782     );
    783 
    784   return AsciiBSPrintUnicodeFormat (StartOfBuffer, BufferSize, FormatString, (BASE_LIST)BaseListMarker);
    785 }
    786 
    787 /**
    788   Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated
    789   ASCII format string and a BASE_LIST argument list.
    790 
    791   Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer
    792   and BufferSize.
    793   The ASCII string is produced by parsing the format string specified by FormatString.
    794   Arguments are pulled from the variable argument list specified by Marker based on
    795   the contents of the format string.
    796   The number of ASCII characters in the produced output buffer is returned not including
    797   the Null-terminator.
    798   If BufferSize is 0, then no output buffer is produced and 0 is returned.
    799 
    800   If BufferSize > 0 and StartOfBuffer is NULL, then ASSERT().
    801   If BufferSize > 0 and FormatString is NULL, then ASSERT().
    802   If BufferSize > 0 and FormatString is not aligned on a 16-bit boundary, then ASSERT().
    803   If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than
    804   PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, then
    805   ASSERT().
    806   If PcdMaximumAsciiStringLength is not zero, and produced Null-terminated ASCII string
    807   contains more than PcdMaximumAsciiStringLength ASCII characters not including the
    808   Null-terminator, then ASSERT().
    809 
    810   @param  StartOfBuffer   A pointer to the output buffer for the produced Null-terminated
    811                           ASCII string.
    812   @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.
    813   @param  FormatString    Null-terminated Unicode format string.
    814   @param  Marker          BASE_LIST marker for the variable argument list.
    815 
    816   @return The number of ASCII characters in the produced output buffer not including the
    817           Null-terminator.
    818 
    819 **/
    820 UINTN
    821 EFIAPI
    822 AsciiBSPrintUnicodeFormat (
    823   OUT CHAR8         *StartOfBuffer,
    824   IN  UINTN         BufferSize,
    825   IN  CONST CHAR16  *FormatString,
    826   IN  BASE_LIST     Marker
    827   )
    828 {
    829   return mPrint2Protocol->AsciiBSPrintUnicodeFormat (StartOfBuffer, BufferSize, FormatString, Marker);
    830 }
    831 
    832 /**
    833   Produces a Null-terminated ASCII string in an output buffer based on a Null-terminated
    834   ASCII format string and  variable argument list.
    835 
    836   Produces a Null-terminated ASCII string in the output buffer specified by StartOfBuffer
    837   and BufferSize.
    838   The ASCII string is produced by parsing the format string specified by FormatString.
    839   Arguments are pulled from the variable argument list based on the contents of the
    840   format string.
    841   The number of ASCII characters in the produced output buffer is returned not including
    842   the Null-terminator.
    843   If BufferSize is 0, then no output buffer is produced and 0 is returned.
    844 
    845   If BufferSize > 0 and StartOfBuffer is NULL, then ASSERT().
    846   If BufferSize > 0 and FormatString is NULL, then ASSERT().
    847   If BufferSize > 0 and FormatString is not aligned on a 16-bit boundary, then ASSERT().
    848   If PcdMaximumUnicodeStringLength is not zero, and FormatString contains more than
    849   PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, then
    850   ASSERT().
    851   If PcdMaximumAsciiStringLength is not zero, and produced Null-terminated ASCII string
    852   contains more than PcdMaximumAsciiStringLength ASCII characters not including the
    853   Null-terminator, then ASSERT().
    854 
    855   @param  StartOfBuffer   A pointer to the output buffer for the produced Null-terminated
    856                           ASCII string.
    857   @param  BufferSize      The size, in bytes, of the output buffer specified by StartOfBuffer.
    858   @param  FormatString    Null-terminated Unicode format string.
    859   @param  ...             Variable argument list whose contents are accessed based on the
    860                           format string specified by FormatString.
    861 
    862   @return The number of ASCII characters in the produced output buffer not including the
    863           Null-terminator.
    864 
    865 **/
    866 UINTN
    867 EFIAPI
    868 AsciiSPrintUnicodeFormat (
    869   OUT CHAR8         *StartOfBuffer,
    870   IN  UINTN         BufferSize,
    871   IN  CONST CHAR16  *FormatString,
    872   ...
    873   )
    874 {
    875   VA_LIST Marker;
    876   UINTN   NumberOfPrinted;
    877 
    878   VA_START (Marker, FormatString);
    879   NumberOfPrinted = AsciiVSPrintUnicodeFormat (StartOfBuffer, BufferSize, FormatString, Marker);
    880   VA_END (Marker);
    881   return NumberOfPrinted;
    882 }
    883 
    884 
    885 /**
    886   Converts a decimal value to a Null-terminated ASCII string.
    887 
    888   Converts the decimal number specified by Value to a Null-terminated ASCII string
    889   specified by Buffer containing at most Width characters. No padding of spaces
    890   is ever performed.
    891   If Width is 0 then a width of  MAXIMUM_VALUE_CHARACTERS is assumed.
    892   The number of ASCII characters in Buffer is returned not including the Null-terminator.
    893   If the conversion contains more than Width characters, then only the first Width
    894   characters are returned, and the total number of characters required to perform
    895   the conversion is returned.
    896   Additional conversion parameters are specified in Flags.
    897   The Flags bit LEFT_JUSTIFY is always ignored.
    898   All conversions are left justified in Buffer.
    899   If Width is 0, PREFIX_ZERO is ignored in Flags.
    900   If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas
    901   are inserted every 3rd digit starting from the right.
    902   If RADIX_HEX is set in Flags, then the output buffer will be
    903   formatted in hexadecimal format.
    904   If Value is < 0 and RADIX_HEX is not set in Flags, then the fist character in Buffer is a '-'.
    905   If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,
    906   then Buffer is padded with '0' characters so the combination of the optional '-'
    907   sign character, '0' characters, digit characters for Value, and the Null-terminator
    908   add up to Width characters.
    909 
    910   If Buffer is NULL, then ASSERT().
    911   If unsupported bits are set in Flags, then ASSERT().
    912   If both COMMA_TYPE and RADIX_HEX are set in Flags, then ASSERT().
    913   If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()
    914 
    915   @param  Buffer  Pointer to the output buffer for the produced Null-terminated
    916                   ASCII string.
    917   @param  Flags   The bitmask of flags that specify left justification, zero pad, and commas.
    918   @param  Value   The 64-bit signed value to convert to a string.
    919   @param  Width   The maximum number of ASCII characters to place in Buffer, not including
    920                   the Null-terminator.
    921 
    922   @return The number of ASCII characters in Buffer not including the Null-terminator.
    923 
    924 **/
    925 UINTN
    926 EFIAPI
    927 AsciiValueToString (
    928   OUT CHAR8      *Buffer,
    929   IN  UINTN      Flags,
    930   IN  INT64      Value,
    931   IN  UINTN      Width
    932   )
    933 {
    934   return mPrint2Protocol->AsciiValueToString (Buffer, Flags, Value, Width);
    935 }
    936 
    937 #define PREFIX_SIGN           BIT1
    938 #define PREFIX_BLANK          BIT2
    939 #define LONG_TYPE             BIT4
    940 #define OUTPUT_UNICODE        BIT6
    941 #define FORMAT_UNICODE        BIT8
    942 #define PAD_TO_WIDTH          BIT9
    943 #define ARGUMENT_UNICODE      BIT10
    944 #define PRECISION             BIT11
    945 #define ARGUMENT_REVERSED     BIT12
    946 #define COUNT_ONLY_NO_PRINT   BIT13
    947 #define UNSIGNED_TYPE         BIT14
    948 
    949 //
    950 // Record date and time information
    951 //
    952 typedef struct {
    953   UINT16  Year;
    954   UINT8   Month;
    955   UINT8   Day;
    956   UINT8   Hour;
    957   UINT8   Minute;
    958   UINT8   Second;
    959   UINT8   Pad1;
    960   UINT32  Nanosecond;
    961   INT16   TimeZone;
    962   UINT8   Daylight;
    963   UINT8   Pad2;
    964 } TIME;
    965 
    966 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    967 
    968 /**
    969   Internal function that convert a number to a string in Buffer.
    970 
    971   Print worker function that converts a decimal or hexadecimal number to an ASCII string in Buffer.
    972 
    973   @param  Buffer    Location to place the ASCII string of Value.
    974   @param  Value     The value to convert to a Decimal or Hexadecimal string in Buffer.
    975   @param  Radix     Radix of the value
    976 
    977   @return A pointer to the end of buffer filled with ASCII string.
    978 
    979 **/
    980 CHAR8 *
    981 InternalPrintLibValueToString (
    982   IN OUT CHAR8  *Buffer,
    983   IN INT64      Value,
    984   IN UINTN      Radix
    985   )
    986 {
    987   UINT32  Remainder;
    988 
    989   //
    990   // Loop to convert one digit at a time in reverse order
    991   //
    992   *Buffer = 0;
    993   do {
    994     Value = (INT64)DivU64x32Remainder ((UINT64)Value, (UINT32)Radix, &Remainder);
    995     *(++Buffer) = mHexStr[Remainder];
    996   } while (Value != 0);
    997 
    998   //
    999   // Return pointer of the end of filled buffer.
   1000   //
   1001   return Buffer;
   1002 }
   1003 
   1004 /**
   1005   Worker function that produces a Null-terminated string in an output buffer
   1006   based on a Null-terminated format string and a VA_LIST argument list.
   1007 
   1008   VSPrint function to process format and place the results in Buffer. Since a
   1009   VA_LIST is used this routine allows the nesting of Vararg routines. Thus
   1010   this is the main print working routine.
   1011 
   1012   If COUNT_ONLY_NO_PRINT is set in Flags, Buffer will not be modified at all.
   1013 
   1014   @param[out] Buffer          The character buffer to print the results of the
   1015                               parsing of Format into.
   1016   @param[in]  BufferSize      The maximum number of characters to put into
   1017                               buffer.
   1018   @param[in]  Flags           Initial flags value.
   1019                               Can only have FORMAT_UNICODE, OUTPUT_UNICODE,
   1020                               and COUNT_ONLY_NO_PRINT set.
   1021   @param[in]  Format          A Null-terminated format string.
   1022   @param[in]  VaListMarker    VA_LIST style variable argument list consumed by
   1023                               processing Format.
   1024   @param[in]  BaseListMarker  BASE_LIST style variable argument list consumed
   1025                               by processing Format.
   1026 
   1027   @return The number of characters printed not including the Null-terminator.
   1028           If COUNT_ONLY_NO_PRINT was set returns the same, but without any
   1029           modification to Buffer.
   1030 
   1031 **/
   1032 UINTN
   1033 InternalPrintLibSPrintMarker (
   1034   OUT CHAR8        *Buffer,
   1035   IN  UINTN        BufferSize,
   1036   IN  UINTN        Flags,
   1037   IN  CONST CHAR8  *Format,
   1038   IN  VA_LIST      VaListMarker,   OPTIONAL
   1039   IN  BASE_LIST    BaseListMarker  OPTIONAL
   1040   );
   1041 
   1042 /**
   1043   Worker function that produces a Null-terminated string in an output buffer
   1044   based on a Null-terminated format string and variable argument list.
   1045 
   1046   VSPrint function to process format and place the results in Buffer. Since a
   1047   VA_LIST is used this routine allows the nesting of Vararg routines. Thus
   1048   this is the main print working routine
   1049 
   1050   @param  StartOfBuffer The character buffer to print the results of the parsing
   1051                         of Format into.
   1052   @param  BufferSize    The maximum number of characters to put into buffer.
   1053                         Zero means no limit.
   1054   @param  Flags         Initial flags value.
   1055                         Can only have FORMAT_UNICODE and OUTPUT_UNICODE set
   1056   @param  FormatString  A Null-terminated format string.
   1057   @param  ...           The variable argument list.
   1058 
   1059   @return The number of characters printed.
   1060 
   1061 **/
   1062 UINTN
   1063 EFIAPI
   1064 InternalPrintLibSPrint (
   1065   OUT CHAR8        *StartOfBuffer,
   1066   IN  UINTN        BufferSize,
   1067   IN  UINTN        Flags,
   1068   IN  CONST CHAR8  *FormatString,
   1069   ...
   1070   )
   1071 {
   1072   VA_LIST  Marker;
   1073   UINTN    NumberOfPrinted;
   1074 
   1075   VA_START (Marker, FormatString);
   1076   NumberOfPrinted = InternalPrintLibSPrintMarker (StartOfBuffer, BufferSize, Flags, FormatString, Marker, NULL);
   1077   VA_END (Marker);
   1078   return NumberOfPrinted;
   1079 }
   1080 
   1081 #define WARNING_STATUS_NUMBER         5
   1082 #define ERROR_STATUS_NUMBER           33
   1083 
   1084 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 * CONST mStatusString[] = {
   1085   "Success",                      //  RETURN_SUCCESS                = 0
   1086   "Warning Unknown Glyph",        //  RETURN_WARN_UNKNOWN_GLYPH     = 1
   1087   "Warning Delete Failure",       //  RETURN_WARN_DELETE_FAILURE    = 2
   1088   "Warning Write Failure",        //  RETURN_WARN_WRITE_FAILURE     = 3
   1089   "Warning Buffer Too Small",     //  RETURN_WARN_BUFFER_TOO_SMALL  = 4
   1090   "Warning Stale Data",           //  RETURN_WARN_STALE_DATA        = 5
   1091   "Load Error",                   //  RETURN_LOAD_ERROR             = 1  | MAX_BIT
   1092   "Invalid Parameter",            //  RETURN_INVALID_PARAMETER      = 2  | MAX_BIT
   1093   "Unsupported",                  //  RETURN_UNSUPPORTED            = 3  | MAX_BIT
   1094   "Bad Buffer Size",              //  RETURN_BAD_BUFFER_SIZE        = 4  | MAX_BIT
   1095   "Buffer Too Small",             //  RETURN_BUFFER_TOO_SMALL,      = 5  | MAX_BIT
   1096   "Not Ready",                    //  RETURN_NOT_READY              = 6  | MAX_BIT
   1097   "Device Error",                 //  RETURN_DEVICE_ERROR           = 7  | MAX_BIT
   1098   "Write Protected",              //  RETURN_WRITE_PROTECTED        = 8  | MAX_BIT
   1099   "Out of Resources",             //  RETURN_OUT_OF_RESOURCES       = 9  | MAX_BIT
   1100   "Volume Corrupt",               //  RETURN_VOLUME_CORRUPTED       = 10 | MAX_BIT
   1101   "Volume Full",                  //  RETURN_VOLUME_FULL            = 11 | MAX_BIT
   1102   "No Media",                     //  RETURN_NO_MEDIA               = 12 | MAX_BIT
   1103   "Media changed",                //  RETURN_MEDIA_CHANGED          = 13 | MAX_BIT
   1104   "Not Found",                    //  RETURN_NOT_FOUND              = 14 | MAX_BIT
   1105   "Access Denied",                //  RETURN_ACCESS_DENIED          = 15 | MAX_BIT
   1106   "No Response",                  //  RETURN_NO_RESPONSE            = 16 | MAX_BIT
   1107   "No mapping",                   //  RETURN_NO_MAPPING             = 17 | MAX_BIT
   1108   "Time out",                     //  RETURN_TIMEOUT                = 18 | MAX_BIT
   1109   "Not started",                  //  RETURN_NOT_STARTED            = 19 | MAX_BIT
   1110   "Already started",              //  RETURN_ALREADY_STARTED        = 20 | MAX_BIT
   1111   "Aborted",                      //  RETURN_ABORTED                = 21 | MAX_BIT
   1112   "ICMP Error",                   //  RETURN_ICMP_ERROR             = 22 | MAX_BIT
   1113   "TFTP Error",                   //  RETURN_TFTP_ERROR             = 23 | MAX_BIT
   1114   "Protocol Error",               //  RETURN_PROTOCOL_ERROR         = 24 | MAX_BIT
   1115   "Incompatible Version",         //  RETURN_INCOMPATIBLE_VERSION   = 25 | MAX_BIT
   1116   "Security Violation",           //  RETURN_SECURITY_VIOLATION     = 26 | MAX_BIT
   1117   "CRC Error",                    //  RETURN_CRC_ERROR              = 27 | MAX_BIT
   1118   "End of Media",                 //  RETURN_END_OF_MEDIA           = 28 | MAX_BIT
   1119   "Reserved (29)",                //  RESERVED                      = 29 | MAX_BIT
   1120   "Reserved (30)",                //  RESERVED                      = 30 | MAX_BIT
   1121   "End of File",                  //  RETURN_END_OF_FILE            = 31 | MAX_BIT
   1122   "Invalid Language",             //  RETURN_INVALID_LANGUAGE       = 32 | MAX_BIT
   1123   "Compromised Data"              //  RETURN_COMPROMISED_DATA       = 33 | MAX_BIT
   1124 };
   1125 
   1126 /**
   1127   Internal function that places the character into the Buffer.
   1128 
   1129   Internal function that places ASCII or Unicode character into the Buffer.
   1130 
   1131   @param  Buffer      The buffer to place the Unicode or ASCII string.
   1132   @param  EndBuffer   The end of the input Buffer. No characters will be
   1133                       placed after that.
   1134   @param  Length      The count of character to be placed into Buffer.
   1135                       (Negative value indicates no buffer fill.)
   1136   @param  Character   The character to be placed into Buffer.
   1137   @param  Increment   The character increment in Buffer.
   1138 
   1139   @return Buffer.
   1140 
   1141 **/
   1142 CHAR8 *
   1143 InternalPrintLibFillBuffer (
   1144   OUT CHAR8   *Buffer,
   1145   IN  CHAR8   *EndBuffer,
   1146   IN  INTN    Length,
   1147   IN  UINTN   Character,
   1148   IN  INTN    Increment
   1149   )
   1150 {
   1151   INTN  Index;
   1152 
   1153   for (Index = 0; Index < Length && Buffer < EndBuffer; Index++) {
   1154     *Buffer = (CHAR8) Character;
   1155     if (Increment != 1) {
   1156       *(Buffer + 1) = (CHAR8)(Character >> 8);
   1157     }
   1158     Buffer += Increment;
   1159   }
   1160 
   1161   return Buffer;
   1162 }
   1163 
   1164 /**
   1165   Worker function that produces a Null-terminated string in an output buffer
   1166   based on a Null-terminated format string and a VA_LIST argument list.
   1167 
   1168   VSPrint function to process format and place the results in Buffer. Since a
   1169   VA_LIST is used this routine allows the nesting of Vararg routines. Thus
   1170   this is the main print working routine.
   1171 
   1172   If COUNT_ONLY_NO_PRINT is set in Flags, Buffer will not be modified at all.
   1173 
   1174   @param[out] Buffer          The character buffer to print the results of the
   1175                               parsing of Format into.
   1176   @param[in]  BufferSize      The maximum number of characters to put into
   1177                               buffer.
   1178   @param[in]  Flags           Initial flags value.
   1179                               Can only have FORMAT_UNICODE, OUTPUT_UNICODE,
   1180                               and COUNT_ONLY_NO_PRINT set.
   1181   @param[in]  Format          A Null-terminated format string.
   1182   @param[in]  VaListMarker    VA_LIST style variable argument list consumed by
   1183                               processing Format.
   1184   @param[in]  BaseListMarker  BASE_LIST style variable argument list consumed
   1185                               by processing Format.
   1186 
   1187   @return The number of characters printed not including the Null-terminator.
   1188           If COUNT_ONLY_NO_PRINT was set returns the same, but without any
   1189           modification to Buffer.
   1190 
   1191 **/
   1192 UINTN
   1193 InternalPrintLibSPrintMarker (
   1194   OUT CHAR8        *Buffer,
   1195   IN  UINTN        BufferSize,
   1196   IN  UINTN        Flags,
   1197   IN  CONST CHAR8  *Format,
   1198   IN  VA_LIST      VaListMarker,   OPTIONAL
   1199   IN  BASE_LIST    BaseListMarker  OPTIONAL
   1200   )
   1201 {
   1202   CHAR8             *OriginalBuffer;
   1203   CHAR8             *EndBuffer;
   1204   CHAR8             ValueBuffer[MAXIMUM_VALUE_CHARACTERS];
   1205   UINT32            BytesPerOutputCharacter;
   1206   UINTN             BytesPerFormatCharacter;
   1207   UINTN             FormatMask;
   1208   UINTN             FormatCharacter;
   1209   UINTN             Width;
   1210   UINTN             Precision;
   1211   INT64             Value;
   1212   CONST CHAR8       *ArgumentString;
   1213   UINTN             Character;
   1214   GUID              *TmpGuid;
   1215   TIME              *TmpTime;
   1216   UINTN             Count;
   1217   UINTN             ArgumentMask;
   1218   INTN              BytesPerArgumentCharacter;
   1219   UINTN             ArgumentCharacter;
   1220   BOOLEAN           Done;
   1221   UINTN             Index;
   1222   CHAR8             Prefix;
   1223   BOOLEAN           ZeroPad;
   1224   BOOLEAN           Comma;
   1225   UINTN             Digits;
   1226   UINTN             Radix;
   1227   RETURN_STATUS     Status;
   1228   UINT32            GuidData1;
   1229   UINT16            GuidData2;
   1230   UINT16            GuidData3;
   1231   UINTN             LengthToReturn;
   1232 
   1233   //
   1234   // If you change this code be sure to match the 2 versions of this function.
   1235   // Nearly identical logic is found in the BasePrintLib and
   1236   // DxePrintLibPrint2Protocol (both PrintLib instances).
   1237   //
   1238 
   1239   if ((Flags & COUNT_ONLY_NO_PRINT) != 0) {
   1240     if (BufferSize == 0) {
   1241       Buffer = NULL;
   1242     }
   1243   } else {
   1244     //
   1245     // We can run without a Buffer for counting only.
   1246     //
   1247     if (BufferSize == 0) {
   1248       return 0;
   1249     }
   1250     ASSERT (Buffer != NULL);
   1251   }
   1252 
   1253   if ((Flags & OUTPUT_UNICODE) != 0) {
   1254     BytesPerOutputCharacter = 2;
   1255   } else {
   1256     BytesPerOutputCharacter = 1;
   1257   }
   1258 
   1259   LengthToReturn = 0;
   1260   EndBuffer = NULL;
   1261   OriginalBuffer = NULL;
   1262 
   1263   //
   1264   // Reserve space for the Null terminator.
   1265   //
   1266   if (Buffer != NULL) {
   1267     BufferSize--;
   1268     OriginalBuffer = Buffer;
   1269 
   1270     //
   1271     // Set the tag for the end of the input Buffer.
   1272     //
   1273     EndBuffer = Buffer + BufferSize * BytesPerOutputCharacter;
   1274   }
   1275 
   1276   if ((Flags & FORMAT_UNICODE) != 0) {
   1277     //
   1278     // Make sure format string cannot contain more than PcdMaximumUnicodeStringLength
   1279     // Unicode characters if PcdMaximumUnicodeStringLength is not zero.
   1280     //
   1281     ASSERT (StrSize ((CHAR16 *) Format) != 0);
   1282     BytesPerFormatCharacter = 2;
   1283     FormatMask = 0xffff;
   1284   } else {
   1285     //
   1286     // Make sure format string cannot contain more than PcdMaximumAsciiStringLength
   1287     // Ascii characters if PcdMaximumAsciiStringLength is not zero.
   1288     //
   1289     ASSERT (AsciiStrSize (Format) != 0);
   1290     BytesPerFormatCharacter = 1;
   1291     FormatMask = 0xff;
   1292   }
   1293 
   1294   //
   1295   // Get the first character from the format string
   1296   //
   1297   FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
   1298 
   1299   //
   1300   // Loop until the end of the format string is reached or the output buffer is full
   1301   //
   1302   while (FormatCharacter != 0) {
   1303     if ((Buffer != NULL) && (Buffer >= EndBuffer)) {
   1304       break;
   1305     }
   1306     //
   1307     // Clear all the flag bits except those that may have been passed in
   1308     //
   1309     Flags &= (UINTN) (OUTPUT_UNICODE | FORMAT_UNICODE | COUNT_ONLY_NO_PRINT);
   1310 
   1311     //
   1312     // Set the default width to zero, and the default precision to 1
   1313     //
   1314     Width     = 0;
   1315     Precision = 1;
   1316     Prefix    = 0;
   1317     Comma     = FALSE;
   1318     ZeroPad   = FALSE;
   1319     Count     = 0;
   1320     Digits    = 0;
   1321 
   1322     switch (FormatCharacter) {
   1323     case '%':
   1324       //
   1325       // Parse Flags and Width
   1326       //
   1327       for (Done = FALSE; !Done; ) {
   1328         Format += BytesPerFormatCharacter;
   1329         FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
   1330         switch (FormatCharacter) {
   1331         case '.':
   1332           Flags |= PRECISION;
   1333           break;
   1334         case '-':
   1335           Flags |= LEFT_JUSTIFY;
   1336           break;
   1337         case '+':
   1338           Flags |= PREFIX_SIGN;
   1339           break;
   1340         case ' ':
   1341           Flags |= PREFIX_BLANK;
   1342           break;
   1343         case ',':
   1344           Flags |= COMMA_TYPE;
   1345           break;
   1346         case 'L':
   1347         case 'l':
   1348           Flags |= LONG_TYPE;
   1349           break;
   1350         case '*':
   1351           if ((Flags & PRECISION) == 0) {
   1352             Flags |= PAD_TO_WIDTH;
   1353             if (BaseListMarker == NULL) {
   1354               Width = VA_ARG (VaListMarker, UINTN);
   1355             } else {
   1356               Width = BASE_ARG (BaseListMarker, UINTN);
   1357             }
   1358           } else {
   1359             if (BaseListMarker == NULL) {
   1360               Precision = VA_ARG (VaListMarker, UINTN);
   1361             } else {
   1362               Precision = BASE_ARG (BaseListMarker, UINTN);
   1363             }
   1364           }
   1365           break;
   1366         case '0':
   1367           if ((Flags & PRECISION) == 0) {
   1368             Flags |= PREFIX_ZERO;
   1369           }
   1370         case '1':
   1371         case '2':
   1372         case '3':
   1373         case '4':
   1374         case '5':
   1375         case '6':
   1376         case '7':
   1377         case '8':
   1378         case '9':
   1379           for (Count = 0; ((FormatCharacter >= '0') &&  (FormatCharacter <= '9')); ){
   1380             Count = (Count * 10) + FormatCharacter - '0';
   1381             Format += BytesPerFormatCharacter;
   1382             FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
   1383           }
   1384           Format -= BytesPerFormatCharacter;
   1385           if ((Flags & PRECISION) == 0) {
   1386             Flags |= PAD_TO_WIDTH;
   1387             Width = Count;
   1388           } else {
   1389             Precision = Count;
   1390           }
   1391           break;
   1392 
   1393         case '\0':
   1394           //
   1395           // Make no output if Format string terminates unexpectedly when
   1396           // looking up for flag, width, precision and type.
   1397           //
   1398           Format   -= BytesPerFormatCharacter;
   1399           Precision = 0;
   1400           //
   1401           // break skipped on purpose.
   1402           //
   1403         default:
   1404           Done = TRUE;
   1405           break;
   1406         }
   1407       }
   1408 
   1409       //
   1410       // Handle each argument type
   1411       //
   1412       switch (FormatCharacter) {
   1413       case 'p':
   1414         //
   1415         // Flag space, +, 0, L & l are invalid for type p.
   1416         //
   1417         Flags &= ~((UINTN) (PREFIX_BLANK | PREFIX_SIGN | PREFIX_ZERO | LONG_TYPE));
   1418         if (sizeof (VOID *) > 4) {
   1419           Flags |= LONG_TYPE;
   1420         }
   1421         //
   1422         // break skipped on purpose
   1423         //
   1424       case 'X':
   1425         Flags |= PREFIX_ZERO;
   1426         //
   1427         // break skipped on purpose
   1428         //
   1429       case 'x':
   1430         Flags |= RADIX_HEX;
   1431         //
   1432         // break skipped on purpose
   1433         //
   1434       case 'u':
   1435         if ((Flags & RADIX_HEX) == 0) {
   1436           Flags &= ~((UINTN) (PREFIX_SIGN));
   1437           Flags |= UNSIGNED_TYPE;
   1438         }
   1439         //
   1440         // break skipped on purpose
   1441         //
   1442       case 'd':
   1443         if ((Flags & LONG_TYPE) == 0) {
   1444           //
   1445           // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
   1446           // This assumption is made so the format string definition is compatible with the ANSI C
   1447           // Specification for formatted strings.  It is recommended that the Base Types be used
   1448           // everywhere, but in this one case, compliance with ANSI C is more important, and
   1449           // provides an implementation that is compatible with that largest possible set of CPU
   1450           // architectures.  This is why the type "int" is used in this one case.
   1451           //
   1452           if (BaseListMarker == NULL) {
   1453             Value = VA_ARG (VaListMarker, int);
   1454           } else {
   1455             Value = BASE_ARG (BaseListMarker, int);
   1456           }
   1457         } else {
   1458           if (BaseListMarker == NULL) {
   1459             Value = VA_ARG (VaListMarker, INT64);
   1460           } else {
   1461             Value = BASE_ARG (BaseListMarker, INT64);
   1462           }
   1463         }
   1464         if ((Flags & PREFIX_BLANK) != 0) {
   1465           Prefix = ' ';
   1466         }
   1467         if ((Flags & PREFIX_SIGN) != 0) {
   1468           Prefix = '+';
   1469         }
   1470         if ((Flags & COMMA_TYPE) != 0) {
   1471           Comma = TRUE;
   1472         }
   1473         if ((Flags & RADIX_HEX) == 0) {
   1474           Radix = 10;
   1475           if (Comma) {
   1476             Flags &= ~((UINTN) PREFIX_ZERO);
   1477             Precision = 1;
   1478           }
   1479           if (Value < 0 && (Flags & UNSIGNED_TYPE) == 0) {
   1480             Flags |= PREFIX_SIGN;
   1481             Prefix = '-';
   1482             Value = -Value;
   1483           } else if ((Flags & UNSIGNED_TYPE) != 0 && (Flags & LONG_TYPE) == 0) {
   1484             //
   1485             // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
   1486             // This assumption is made so the format string definition is compatible with the ANSI C
   1487             // Specification for formatted strings.  It is recommended that the Base Types be used
   1488             // everywhere, but in this one case, compliance with ANSI C is more important, and
   1489             // provides an implementation that is compatible with that largest possible set of CPU
   1490             // architectures.  This is why the type "unsigned int" is used in this one case.
   1491             //
   1492             Value = (unsigned int)Value;
   1493           }
   1494         } else {
   1495           Radix = 16;
   1496           Comma = FALSE;
   1497           if ((Flags & LONG_TYPE) == 0 && Value < 0) {
   1498             //
   1499             // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
   1500             // This assumption is made so the format string definition is compatible with the ANSI C
   1501             // Specification for formatted strings.  It is recommended that the Base Types be used
   1502             // everywhere, but in this one case, compliance with ANSI C is more important, and
   1503             // provides an implementation that is compatible with that largest possible set of CPU
   1504             // architectures.  This is why the type "unsigned int" is used in this one case.
   1505             //
   1506             Value = (unsigned int)Value;
   1507           }
   1508         }
   1509         //
   1510         // Convert Value to a reversed string
   1511         //
   1512         Count = InternalPrintLibValueToString (ValueBuffer, Value, Radix) - ValueBuffer;
   1513         if (Value == 0 && Precision == 0) {
   1514           Count = 0;
   1515         }
   1516         ArgumentString = (CHAR8 *)ValueBuffer + Count;
   1517 
   1518         Digits = Count % 3;
   1519         if (Digits != 0) {
   1520           Digits = 3 - Digits;
   1521         }
   1522         if (Comma && Count != 0) {
   1523           Count += ((Count - 1) / 3);
   1524         }
   1525         if (Prefix != 0) {
   1526           Count++;
   1527           Precision++;
   1528         }
   1529         Flags |= ARGUMENT_REVERSED;
   1530         ZeroPad = TRUE;
   1531         if ((Flags & PREFIX_ZERO) != 0) {
   1532           if ((Flags & LEFT_JUSTIFY) == 0) {
   1533             if ((Flags & PAD_TO_WIDTH) != 0) {
   1534               if ((Flags & PRECISION) == 0) {
   1535                 Precision = Width;
   1536               }
   1537             }
   1538           }
   1539         }
   1540         break;
   1541 
   1542       case 's':
   1543       case 'S':
   1544         Flags |= ARGUMENT_UNICODE;
   1545         //
   1546         // break skipped on purpose
   1547         //
   1548       case 'a':
   1549         if (BaseListMarker == NULL) {
   1550           ArgumentString = VA_ARG (VaListMarker, CHAR8 *);
   1551         } else {
   1552           ArgumentString = BASE_ARG (BaseListMarker, CHAR8 *);
   1553         }
   1554         if (ArgumentString == NULL) {
   1555           Flags &= (~(UINTN)ARGUMENT_UNICODE);
   1556           ArgumentString = "<null string>";
   1557         }
   1558         //
   1559         // Set the default precision for string to be zero if not specified.
   1560         //
   1561         if ((Flags & PRECISION) == 0) {
   1562           Precision = 0;
   1563         }
   1564         break;
   1565 
   1566       case 'c':
   1567         if (BaseListMarker == NULL) {
   1568           Character = VA_ARG (VaListMarker, UINTN) & 0xffff;
   1569         } else {
   1570           Character = BASE_ARG (BaseListMarker, UINTN) & 0xffff;
   1571         }
   1572         ArgumentString = (CHAR8 *)&Character;
   1573         Flags |= ARGUMENT_UNICODE;
   1574         break;
   1575 
   1576       case 'g':
   1577         if (BaseListMarker == NULL) {
   1578           TmpGuid = VA_ARG (VaListMarker, GUID *);
   1579         } else {
   1580           TmpGuid = BASE_ARG (BaseListMarker, GUID *);
   1581         }
   1582         if (TmpGuid == NULL) {
   1583           ArgumentString = "<null guid>";
   1584         } else {
   1585           GuidData1 = ReadUnaligned32 (&(TmpGuid->Data1));
   1586           GuidData2 = ReadUnaligned16 (&(TmpGuid->Data2));
   1587           GuidData3 = ReadUnaligned16 (&(TmpGuid->Data3));
   1588           InternalPrintLibSPrint (
   1589             ValueBuffer,
   1590             MAXIMUM_VALUE_CHARACTERS,
   1591             0,
   1592             "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
   1593             GuidData1,
   1594             GuidData2,
   1595             GuidData3,
   1596             TmpGuid->Data4[0],
   1597             TmpGuid->Data4[1],
   1598             TmpGuid->Data4[2],
   1599             TmpGuid->Data4[3],
   1600             TmpGuid->Data4[4],
   1601             TmpGuid->Data4[5],
   1602             TmpGuid->Data4[6],
   1603             TmpGuid->Data4[7]
   1604             );
   1605           ArgumentString = ValueBuffer;
   1606         }
   1607         break;
   1608 
   1609       case 't':
   1610         if (BaseListMarker == NULL) {
   1611           TmpTime = VA_ARG (VaListMarker, TIME *);
   1612         } else {
   1613           TmpTime = BASE_ARG (BaseListMarker, TIME *);
   1614         }
   1615         if (TmpTime == NULL) {
   1616           ArgumentString = "<null time>";
   1617         } else {
   1618           InternalPrintLibSPrint (
   1619             ValueBuffer,
   1620             MAXIMUM_VALUE_CHARACTERS,
   1621             0,
   1622             "%02d/%02d/%04d  %02d:%02d",
   1623             TmpTime->Month,
   1624             TmpTime->Day,
   1625             TmpTime->Year,
   1626             TmpTime->Hour,
   1627             TmpTime->Minute
   1628             );
   1629           ArgumentString = ValueBuffer;
   1630         }
   1631         break;
   1632 
   1633       case 'r':
   1634         if (BaseListMarker == NULL) {
   1635           Status = VA_ARG (VaListMarker, RETURN_STATUS);
   1636         } else {
   1637           Status = BASE_ARG (BaseListMarker, RETURN_STATUS);
   1638         }
   1639         ArgumentString = ValueBuffer;
   1640         if (RETURN_ERROR (Status)) {
   1641           //
   1642           // Clear error bit
   1643           //
   1644           Index = Status & ~MAX_BIT;
   1645           if (Index > 0 && Index <= ERROR_STATUS_NUMBER) {
   1646             ArgumentString = mStatusString [Index + WARNING_STATUS_NUMBER];
   1647           }
   1648         } else {
   1649           Index = Status;
   1650           if (Index <= WARNING_STATUS_NUMBER) {
   1651             ArgumentString = mStatusString [Index];
   1652           }
   1653         }
   1654         if (ArgumentString == ValueBuffer) {
   1655           InternalPrintLibSPrint ((CHAR8 *) ValueBuffer, MAXIMUM_VALUE_CHARACTERS, 0, "%08X", Status);
   1656         }
   1657         break;
   1658 
   1659       case '\r':
   1660         Format += BytesPerFormatCharacter;
   1661         FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
   1662         if (FormatCharacter == '\n') {
   1663           //
   1664           // Translate '\r\n' to '\r\n'
   1665           //
   1666           ArgumentString = "\r\n";
   1667         } else {
   1668           //
   1669           // Translate '\r' to '\r'
   1670           //
   1671           ArgumentString = "\r";
   1672           Format   -= BytesPerFormatCharacter;
   1673         }
   1674         break;
   1675 
   1676       case '\n':
   1677         //
   1678         // Translate '\n' to '\r\n' and '\n\r' to '\r\n'
   1679         //
   1680         ArgumentString = "\r\n";
   1681         Format += BytesPerFormatCharacter;
   1682         FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
   1683         if (FormatCharacter != '\r') {
   1684           Format   -= BytesPerFormatCharacter;
   1685         }
   1686         break;
   1687 
   1688       case '%':
   1689       default:
   1690         //
   1691         // if the type is '%' or unknown, then print it to the screen
   1692         //
   1693         ArgumentString = (CHAR8 *)&FormatCharacter;
   1694         Flags |= ARGUMENT_UNICODE;
   1695         break;
   1696       }
   1697       break;
   1698 
   1699     case '\r':
   1700       Format += BytesPerFormatCharacter;
   1701       FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
   1702       if (FormatCharacter == '\n') {
   1703         //
   1704         // Translate '\r\n' to '\r\n'
   1705         //
   1706         ArgumentString = "\r\n";
   1707       } else {
   1708         //
   1709         // Translate '\r' to '\r'
   1710         //
   1711         ArgumentString = "\r";
   1712         Format   -= BytesPerFormatCharacter;
   1713       }
   1714       break;
   1715 
   1716     case '\n':
   1717       //
   1718       // Translate '\n' to '\r\n' and '\n\r' to '\r\n'
   1719       //
   1720       ArgumentString = "\r\n";
   1721       Format += BytesPerFormatCharacter;
   1722       FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
   1723       if (FormatCharacter != '\r') {
   1724         Format   -= BytesPerFormatCharacter;
   1725       }
   1726       break;
   1727 
   1728     default:
   1729       ArgumentString = (CHAR8 *)&FormatCharacter;
   1730       Flags |= ARGUMENT_UNICODE;
   1731       break;
   1732     }
   1733 
   1734     //
   1735     // Retrieve the ArgumentString attriubutes
   1736     //
   1737     if ((Flags & ARGUMENT_UNICODE) != 0) {
   1738       ArgumentMask = 0xffff;
   1739       BytesPerArgumentCharacter = 2;
   1740     } else {
   1741       ArgumentMask = 0xff;
   1742       BytesPerArgumentCharacter = 1;
   1743     }
   1744     if ((Flags & ARGUMENT_REVERSED) != 0) {
   1745       BytesPerArgumentCharacter = -BytesPerArgumentCharacter;
   1746     } else {
   1747       //
   1748       // Compute the number of characters in ArgumentString and store it in Count
   1749       // ArgumentString is either null-terminated, or it contains Precision characters
   1750       //
   1751       for (Count = 0; Count < Precision || ((Flags & PRECISION) == 0); Count++) {
   1752         ArgumentCharacter = ((ArgumentString[Count * BytesPerArgumentCharacter] & 0xff) | ((ArgumentString[Count * BytesPerArgumentCharacter + 1]) << 8)) & ArgumentMask;
   1753         if (ArgumentCharacter == 0) {
   1754           break;
   1755         }
   1756       }
   1757     }
   1758 
   1759     if (Precision < Count) {
   1760       Precision = Count;
   1761     }
   1762 
   1763     //
   1764     // Pad before the string
   1765     //
   1766     if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH)) {
   1767       LengthToReturn += ((Width - Precision) * BytesPerOutputCharacter);
   1768       if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
   1769         Buffer = InternalPrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);
   1770       }
   1771     }
   1772 
   1773     if (ZeroPad) {
   1774       if (Prefix != 0) {
   1775         LengthToReturn += (1 * BytesPerOutputCharacter);
   1776         if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
   1777           Buffer = InternalPrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);
   1778         }
   1779       }
   1780       LengthToReturn += ((Precision - Count) * BytesPerOutputCharacter);
   1781       if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
   1782         Buffer = InternalPrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, '0', BytesPerOutputCharacter);
   1783       }
   1784     } else {
   1785       LengthToReturn += ((Precision - Count) * BytesPerOutputCharacter);
   1786       if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
   1787         Buffer = InternalPrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, ' ', BytesPerOutputCharacter);
   1788       }
   1789       if (Prefix != 0) {
   1790         LengthToReturn += (1 * BytesPerOutputCharacter);
   1791         if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
   1792           Buffer = InternalPrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);
   1793         }
   1794       }
   1795     }
   1796 
   1797     //
   1798     // Output the Prefix character if it is present
   1799     //
   1800     Index = 0;
   1801     if (Prefix != 0) {
   1802       Index++;
   1803     }
   1804 
   1805     //
   1806     // Copy the string into the output buffer performing the required type conversions
   1807     //
   1808     while (Index < Count) {
   1809       ArgumentCharacter = ((*ArgumentString & 0xff) | (*(ArgumentString + 1) << 8)) & ArgumentMask;
   1810 
   1811       LengthToReturn += (1 * BytesPerOutputCharacter);
   1812       if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
   1813         Buffer = InternalPrintLibFillBuffer (Buffer, EndBuffer, 1, ArgumentCharacter, BytesPerOutputCharacter);
   1814       }
   1815       ArgumentString    += BytesPerArgumentCharacter;
   1816       Index++;
   1817       if (Comma) {
   1818         Digits++;
   1819         if (Digits == 3) {
   1820           Digits = 0;
   1821           Index++;
   1822           if (Index < Count) {
   1823             LengthToReturn += (1 * BytesPerOutputCharacter);
   1824             if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
   1825               Buffer = InternalPrintLibFillBuffer (Buffer, EndBuffer, 1, ',', BytesPerOutputCharacter);
   1826             }
   1827           }
   1828         }
   1829       }
   1830     }
   1831 
   1832     //
   1833     // Pad after the string
   1834     //
   1835     if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH | LEFT_JUSTIFY)) {
   1836       LengthToReturn += ((Width - Precision) * BytesPerOutputCharacter);
   1837       if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
   1838         Buffer = InternalPrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);
   1839       }
   1840     }
   1841 
   1842     //
   1843     // Get the next character from the format string
   1844     //
   1845     Format += BytesPerFormatCharacter;
   1846 
   1847     //
   1848     // Get the next character from the format string
   1849     //
   1850     FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
   1851   }
   1852 
   1853   if ((Flags & COUNT_ONLY_NO_PRINT) != 0) {
   1854     return (LengthToReturn / BytesPerOutputCharacter);
   1855   }
   1856 
   1857   ASSERT (Buffer != NULL);
   1858   //
   1859   // Null terminate the Unicode or ASCII string
   1860   //
   1861   InternalPrintLibFillBuffer (Buffer, EndBuffer + BytesPerOutputCharacter, 1, 0, BytesPerOutputCharacter);
   1862   //
   1863   // Make sure output buffer cannot contain more than PcdMaximumUnicodeStringLength
   1864   // Unicode characters if PcdMaximumUnicodeStringLength is not zero.
   1865   //
   1866   ASSERT ((((Flags & OUTPUT_UNICODE) == 0)) || (StrSize ((CHAR16 *) OriginalBuffer) != 0));
   1867   //
   1868   // Make sure output buffer cannot contain more than PcdMaximumAsciiStringLength
   1869   // ASCII characters if PcdMaximumAsciiStringLength is not zero.
   1870   //
   1871   ASSERT ((((Flags & OUTPUT_UNICODE) != 0)) || (AsciiStrSize (OriginalBuffer) != 0));
   1872 
   1873   return ((Buffer - OriginalBuffer) / BytesPerOutputCharacter);
   1874 }
   1875 
   1876 /**
   1877   Returns the number of characters that would be produced by if the formatted
   1878   output were produced not including the Null-terminator.
   1879 
   1880   If FormatString is NULL, then ASSERT().
   1881   If FormatString is not aligned on a 16-bit boundary, then ASSERT().
   1882 
   1883   @param[in]  FormatString    A Null-terminated Unicode format string.
   1884   @param[in]  Marker          VA_LIST marker for the variable argument list.
   1885 
   1886   @return The number of characters that would be produced, not including the
   1887           Null-terminator.
   1888 **/
   1889 UINTN
   1890 EFIAPI
   1891 SPrintLength (
   1892   IN  CONST CHAR16   *FormatString,
   1893   IN  VA_LIST       Marker
   1894   )
   1895 {
   1896   ASSERT(FormatString != NULL);
   1897   return InternalPrintLibSPrintMarker (NULL, 0, FORMAT_UNICODE | OUTPUT_UNICODE | COUNT_ONLY_NO_PRINT, (CHAR8 *)FormatString, Marker, NULL);
   1898 }
   1899 
   1900 /**
   1901   Returns the number of characters that would be produced by if the formatted
   1902   output were produced not including the Null-terminator.
   1903 
   1904   If FormatString is NULL, then ASSERT().
   1905 
   1906   @param[in]  FormatString    A Null-terminated ASCII format string.
   1907   @param[in]  Marker          VA_LIST marker for the variable argument list.
   1908 
   1909   @return The number of characters that would be produced, not including the
   1910           Null-terminator.
   1911 **/
   1912 UINTN
   1913 EFIAPI
   1914 SPrintLengthAsciiFormat (
   1915   IN  CONST CHAR8   *FormatString,
   1916   IN  VA_LIST       Marker
   1917   )
   1918 {
   1919   ASSERT(FormatString != NULL);
   1920   return InternalPrintLibSPrintMarker (NULL, 0, OUTPUT_UNICODE | COUNT_ONLY_NO_PRINT, (CHAR8 *)FormatString, Marker, NULL);
   1921 }
   1922