Home | History | Annotate | Download | only in BasePrintLib
      1 /** @file
      2   Print Library internal worker functions.
      3 
      4   Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php.
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "PrintLibInternal.h"
     16 
     17 #define WARNING_STATUS_NUMBER         5
     18 #define ERROR_STATUS_NUMBER           33
     19 
     20 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
     21 
     22 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 * CONST mStatusString[] = {
     23   "Success",                      //  RETURN_SUCCESS                = 0
     24   "Warning Unknown Glyph",        //  RETURN_WARN_UNKNOWN_GLYPH     = 1
     25   "Warning Delete Failure",       //  RETURN_WARN_DELETE_FAILURE    = 2
     26   "Warning Write Failure",        //  RETURN_WARN_WRITE_FAILURE     = 3
     27   "Warning Buffer Too Small",     //  RETURN_WARN_BUFFER_TOO_SMALL  = 4
     28   "Warning Stale Data",           //  RETURN_WARN_STALE_DATA        = 5
     29   "Load Error",                   //  RETURN_LOAD_ERROR             = 1  | MAX_BIT
     30   "Invalid Parameter",            //  RETURN_INVALID_PARAMETER      = 2  | MAX_BIT
     31   "Unsupported",                  //  RETURN_UNSUPPORTED            = 3  | MAX_BIT
     32   "Bad Buffer Size",              //  RETURN_BAD_BUFFER_SIZE        = 4  | MAX_BIT
     33   "Buffer Too Small",             //  RETURN_BUFFER_TOO_SMALL,      = 5  | MAX_BIT
     34   "Not Ready",                    //  RETURN_NOT_READY              = 6  | MAX_BIT
     35   "Device Error",                 //  RETURN_DEVICE_ERROR           = 7  | MAX_BIT
     36   "Write Protected",              //  RETURN_WRITE_PROTECTED        = 8  | MAX_BIT
     37   "Out of Resources",             //  RETURN_OUT_OF_RESOURCES       = 9  | MAX_BIT
     38   "Volume Corrupt",               //  RETURN_VOLUME_CORRUPTED       = 10 | MAX_BIT
     39   "Volume Full",                  //  RETURN_VOLUME_FULL            = 11 | MAX_BIT
     40   "No Media",                     //  RETURN_NO_MEDIA               = 12 | MAX_BIT
     41   "Media changed",                //  RETURN_MEDIA_CHANGED          = 13 | MAX_BIT
     42   "Not Found",                    //  RETURN_NOT_FOUND              = 14 | MAX_BIT
     43   "Access Denied",                //  RETURN_ACCESS_DENIED          = 15 | MAX_BIT
     44   "No Response",                  //  RETURN_NO_RESPONSE            = 16 | MAX_BIT
     45   "No mapping",                   //  RETURN_NO_MAPPING             = 17 | MAX_BIT
     46   "Time out",                     //  RETURN_TIMEOUT                = 18 | MAX_BIT
     47   "Not started",                  //  RETURN_NOT_STARTED            = 19 | MAX_BIT
     48   "Already started",              //  RETURN_ALREADY_STARTED        = 20 | MAX_BIT
     49   "Aborted",                      //  RETURN_ABORTED                = 21 | MAX_BIT
     50   "ICMP Error",                   //  RETURN_ICMP_ERROR             = 22 | MAX_BIT
     51   "TFTP Error",                   //  RETURN_TFTP_ERROR             = 23 | MAX_BIT
     52   "Protocol Error",               //  RETURN_PROTOCOL_ERROR         = 24 | MAX_BIT
     53   "Incompatible Version",         //  RETURN_INCOMPATIBLE_VERSION   = 25 | MAX_BIT
     54   "Security Violation",           //  RETURN_SECURITY_VIOLATION     = 26 | MAX_BIT
     55   "CRC Error",                    //  RETURN_CRC_ERROR              = 27 | MAX_BIT
     56   "End of Media",                 //  RETURN_END_OF_MEDIA           = 28 | MAX_BIT
     57   "Reserved (29)",                //  RESERVED                      = 29 | MAX_BIT
     58   "Reserved (30)",                //  RESERVED                      = 30 | MAX_BIT
     59   "End of File",                  //  RETURN_END_OF_FILE            = 31 | MAX_BIT
     60   "Invalid Language",             //  RETURN_INVALID_LANGUAGE       = 32 | MAX_BIT
     61   "Compromised Data"              //  RETURN_COMPROMISED_DATA       = 33 | MAX_BIT
     62 };
     63 
     64 
     65 /**
     66   Internal function that places the character into the Buffer.
     67 
     68   Internal function that places ASCII or Unicode character into the Buffer.
     69 
     70   @param  Buffer      The buffer to place the Unicode or ASCII string.
     71   @param  EndBuffer   The end of the input Buffer. No characters will be
     72                       placed after that.
     73   @param  Length      The count of character to be placed into Buffer.
     74                       (Negative value indicates no buffer fill.)
     75   @param  Character   The character to be placed into Buffer.
     76   @param  Increment   The character increment in Buffer.
     77 
     78   @return Buffer.
     79 
     80 **/
     81 CHAR8 *
     82 BasePrintLibFillBuffer (
     83   OUT CHAR8   *Buffer,
     84   IN  CHAR8   *EndBuffer,
     85   IN  INTN    Length,
     86   IN  UINTN   Character,
     87   IN  INTN    Increment
     88   )
     89 {
     90   INTN  Index;
     91 
     92   for (Index = 0; Index < Length && Buffer < EndBuffer; Index++) {
     93     *Buffer = (CHAR8) Character;
     94     if (Increment != 1) {
     95       *(Buffer + 1) = (CHAR8)(Character >> 8);
     96     }
     97     Buffer += Increment;
     98   }
     99 
    100   return Buffer;
    101 }
    102 
    103 /**
    104   Internal function that convert a number to a string in Buffer.
    105 
    106   Print worker function that converts a decimal or hexadecimal number to an ASCII string in Buffer.
    107 
    108   @param  Buffer    Location to place the ASCII string of Value.
    109   @param  Value     The value to convert to a Decimal or Hexadecimal string in Buffer.
    110   @param  Radix     Radix of the value
    111 
    112   @return A pointer to the end of buffer filled with ASCII string.
    113 
    114 **/
    115 CHAR8 *
    116 BasePrintLibValueToString (
    117   IN OUT CHAR8  *Buffer,
    118   IN INT64      Value,
    119   IN UINTN      Radix
    120   )
    121 {
    122   UINT32  Remainder;
    123 
    124   //
    125   // Loop to convert one digit at a time in reverse order
    126   //
    127   *Buffer = 0;
    128   do {
    129     Value = (INT64)DivU64x32Remainder ((UINT64)Value, (UINT32)Radix, &Remainder);
    130     *(++Buffer) = mHexStr[Remainder];
    131   } while (Value != 0);
    132 
    133   //
    134   // Return pointer of the end of filled buffer.
    135   //
    136   return Buffer;
    137 }
    138 
    139 /**
    140   Internal function that converts a decimal value to a Null-terminated string.
    141 
    142   Converts the decimal number specified by Value to a Null-terminated
    143   string specified by Buffer containing at most Width characters.
    144   If Width is 0 then a width of  MAXIMUM_VALUE_CHARACTERS is assumed.
    145   The total number of characters placed in Buffer is returned.
    146   If the conversion contains more than Width characters, then only the first
    147   Width characters are returned, and the total number of characters
    148   required to perform the conversion is returned.
    149   Additional conversion parameters are specified in Flags.
    150   The Flags bit LEFT_JUSTIFY is always ignored.
    151   All conversions are left justified in Buffer.
    152   If Width is 0, PREFIX_ZERO is ignored in Flags.
    153   If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas
    154   are inserted every 3rd digit starting from the right.
    155   If Value is < 0, then the fist character in Buffer is a '-'.
    156   If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,
    157   then Buffer is padded with '0' characters so the combination of the optional '-'
    158   sign character, '0' characters, digit characters for Value, and the Null-terminator
    159   add up to Width characters.
    160 
    161   If Buffer is NULL, then ASSERT().
    162   If unsupported bits are set in Flags, then ASSERT().
    163   If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()
    164 
    165   @param  Buffer    The pointer to the output buffer for the produced Null-terminated
    166                     string.
    167   @param  Flags     The bitmask of flags that specify left justification, zero pad,
    168                     and commas.
    169   @param  Value     The 64-bit signed value to convert to a string.
    170   @param  Width     The maximum number of characters to place in Buffer, not including
    171                     the Null-terminator.
    172   @param  Increment The character increment in Buffer.
    173 
    174   @return Total number of characters required to perform the conversion.
    175 
    176 **/
    177 UINTN
    178 BasePrintLibConvertValueToString (
    179   IN OUT CHAR8   *Buffer,
    180   IN UINTN       Flags,
    181   IN INT64       Value,
    182   IN UINTN       Width,
    183   IN UINTN       Increment
    184   )
    185 {
    186   CHAR8  *OriginalBuffer;
    187   CHAR8  *EndBuffer;
    188   CHAR8  ValueBuffer[MAXIMUM_VALUE_CHARACTERS];
    189   CHAR8  *ValueBufferPtr;
    190   UINTN  Count;
    191   UINTN  Digits;
    192   UINTN  Index;
    193   UINTN  Radix;
    194 
    195   //
    196   // Make sure Buffer is not NULL and Width < MAXIMUM
    197   //
    198   ASSERT (Buffer != NULL);
    199   ASSERT (Width < MAXIMUM_VALUE_CHARACTERS);
    200   //
    201   // Make sure Flags can only contain supported bits.
    202   //
    203   ASSERT ((Flags & ~(LEFT_JUSTIFY | COMMA_TYPE | PREFIX_ZERO | RADIX_HEX)) == 0);
    204 
    205   //
    206   // If both COMMA_TYPE and RADIX_HEX are set, then ASSERT ()
    207   //
    208   ASSERT (((Flags & COMMA_TYPE) == 0) || ((Flags & RADIX_HEX) == 0));
    209 
    210   OriginalBuffer = Buffer;
    211 
    212   //
    213   // Width is 0 or COMMA_TYPE is set, PREFIX_ZERO is ignored.
    214   //
    215   if (Width == 0 || (Flags & COMMA_TYPE) != 0) {
    216     Flags &= ~((UINTN) PREFIX_ZERO);
    217   }
    218   //
    219   // If Width is 0 then a width of  MAXIMUM_VALUE_CHARACTERS is assumed.
    220   //
    221   if (Width == 0) {
    222     Width = MAXIMUM_VALUE_CHARACTERS - 1;
    223   }
    224   //
    225   // Set the tag for the end of the input Buffer.
    226   //
    227   EndBuffer = Buffer + Width * Increment;
    228 
    229   //
    230   // Convert decimal negative
    231   //
    232   if ((Value < 0) && ((Flags & RADIX_HEX) == 0)) {
    233     Value = -Value;
    234     Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, '-', Increment);
    235     Width--;
    236   }
    237 
    238   //
    239   // Count the length of the value string.
    240   //
    241   Radix = ((Flags & RADIX_HEX) == 0)? 10 : 16;
    242   ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, Value, Radix);
    243   Count = ValueBufferPtr - ValueBuffer;
    244 
    245   //
    246   // Append Zero
    247   //
    248   if ((Flags & PREFIX_ZERO) != 0) {
    249     Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Count, '0', Increment);
    250   }
    251 
    252   //
    253   // Print Comma type for every 3 characters
    254   //
    255   Digits = Count % 3;
    256   if (Digits != 0) {
    257     Digits = 3 - Digits;
    258   }
    259   for (Index = 0; Index < Count; Index++) {
    260     Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, *ValueBufferPtr--, Increment);
    261     if ((Flags & COMMA_TYPE) != 0) {
    262       Digits++;
    263       if (Digits == 3) {
    264         Digits = 0;
    265         if ((Index + 1) < Count) {
    266           Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', Increment);
    267         }
    268       }
    269     }
    270   }
    271 
    272   //
    273   // Print Null-terminator
    274   //
    275   BasePrintLibFillBuffer (Buffer, EndBuffer + Increment, 1, 0, Increment);
    276 
    277   return ((Buffer - OriginalBuffer) / Increment);
    278 }
    279 
    280 /**
    281   Worker function that produces a Null-terminated string in an output buffer
    282   based on a Null-terminated format string and a VA_LIST argument list.
    283 
    284   VSPrint function to process format and place the results in Buffer. Since a
    285   VA_LIST is used this routine allows the nesting of Vararg routines. Thus
    286   this is the main print working routine.
    287 
    288   If COUNT_ONLY_NO_PRINT is set in Flags, Buffer will not be modified at all.
    289 
    290   @param[out] Buffer          The character buffer to print the results of the
    291                               parsing of Format into.
    292   @param[in]  BufferSize      The maximum number of characters to put into
    293                               buffer.
    294   @param[in]  Flags           Initial flags value.
    295                               Can only have FORMAT_UNICODE, OUTPUT_UNICODE,
    296                               and COUNT_ONLY_NO_PRINT set.
    297   @param[in]  Format          A Null-terminated format string.
    298   @param[in]  VaListMarker    VA_LIST style variable argument list consumed by
    299                               processing Format.
    300   @param[in]  BaseListMarker  BASE_LIST style variable argument list consumed
    301                               by processing Format.
    302 
    303   @return The number of characters printed not including the Null-terminator.
    304           If COUNT_ONLY_NO_PRINT was set returns the same, but without any
    305           modification to Buffer.
    306 
    307 **/
    308 UINTN
    309 BasePrintLibSPrintMarker (
    310   OUT CHAR8        *Buffer,
    311   IN  UINTN        BufferSize,
    312   IN  UINTN        Flags,
    313   IN  CONST CHAR8  *Format,
    314   IN  VA_LIST      VaListMarker,   OPTIONAL
    315   IN  BASE_LIST    BaseListMarker  OPTIONAL
    316   )
    317 {
    318   CHAR8             *OriginalBuffer;
    319   CHAR8             *EndBuffer;
    320   CHAR8             ValueBuffer[MAXIMUM_VALUE_CHARACTERS];
    321   UINT32            BytesPerOutputCharacter;
    322   UINTN             BytesPerFormatCharacter;
    323   UINTN             FormatMask;
    324   UINTN             FormatCharacter;
    325   UINTN             Width;
    326   UINTN             Precision;
    327   INT64             Value;
    328   CONST CHAR8       *ArgumentString;
    329   UINTN             Character;
    330   GUID              *TmpGuid;
    331   TIME              *TmpTime;
    332   UINTN             Count;
    333   UINTN             ArgumentMask;
    334   INTN              BytesPerArgumentCharacter;
    335   UINTN             ArgumentCharacter;
    336   BOOLEAN           Done;
    337   UINTN             Index;
    338   CHAR8             Prefix;
    339   BOOLEAN           ZeroPad;
    340   BOOLEAN           Comma;
    341   UINTN             Digits;
    342   UINTN             Radix;
    343   RETURN_STATUS     Status;
    344   UINT32            GuidData1;
    345   UINT16            GuidData2;
    346   UINT16            GuidData3;
    347   UINTN             LengthToReturn;
    348 
    349   //
    350   // If you change this code be sure to match the 2 versions of this function.
    351   // Nearly identical logic is found in the BasePrintLib and
    352   // DxePrintLibPrint2Protocol (both PrintLib instances).
    353   //
    354 
    355   if ((Flags & COUNT_ONLY_NO_PRINT) != 0) {
    356     if (BufferSize == 0) {
    357       Buffer = NULL;
    358     }
    359   } else {
    360     //
    361     // We can run without a Buffer for counting only.
    362     //
    363     if (BufferSize == 0) {
    364       return 0;
    365     }
    366     ASSERT (Buffer != NULL);
    367   }
    368 
    369   if ((Flags & OUTPUT_UNICODE) != 0) {
    370     BytesPerOutputCharacter = 2;
    371   } else {
    372     BytesPerOutputCharacter = 1;
    373   }
    374 
    375   LengthToReturn = 0;
    376   EndBuffer = NULL;
    377   OriginalBuffer = NULL;
    378 
    379   //
    380   // Reserve space for the Null terminator.
    381   //
    382   if (Buffer != NULL) {
    383     BufferSize--;
    384     OriginalBuffer = Buffer;
    385 
    386     //
    387     // Set the tag for the end of the input Buffer.
    388     //
    389     EndBuffer = Buffer + BufferSize * BytesPerOutputCharacter;
    390   }
    391 
    392   if ((Flags & FORMAT_UNICODE) != 0) {
    393     //
    394     // Make sure format string cannot contain more than PcdMaximumUnicodeStringLength
    395     // Unicode characters if PcdMaximumUnicodeStringLength is not zero.
    396     //
    397     ASSERT (StrSize ((CHAR16 *) Format) != 0);
    398     BytesPerFormatCharacter = 2;
    399     FormatMask = 0xffff;
    400   } else {
    401     //
    402     // Make sure format string cannot contain more than PcdMaximumAsciiStringLength
    403     // Ascii characters if PcdMaximumAsciiStringLength is not zero.
    404     //
    405     ASSERT (AsciiStrSize (Format) != 0);
    406     BytesPerFormatCharacter = 1;
    407     FormatMask = 0xff;
    408   }
    409 
    410   //
    411   // Get the first character from the format string
    412   //
    413   FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
    414 
    415   //
    416   // Loop until the end of the format string is reached or the output buffer is full
    417   //
    418   while (FormatCharacter != 0) {
    419     if ((Buffer != NULL) && (Buffer >= EndBuffer)) {
    420       break;
    421     }
    422     //
    423     // Clear all the flag bits except those that may have been passed in
    424     //
    425     Flags &= (UINTN) (OUTPUT_UNICODE | FORMAT_UNICODE | COUNT_ONLY_NO_PRINT);
    426 
    427     //
    428     // Set the default width to zero, and the default precision to 1
    429     //
    430     Width     = 0;
    431     Precision = 1;
    432     Prefix    = 0;
    433     Comma     = FALSE;
    434     ZeroPad   = FALSE;
    435     Count     = 0;
    436     Digits    = 0;
    437 
    438     switch (FormatCharacter) {
    439     case '%':
    440       //
    441       // Parse Flags and Width
    442       //
    443       for (Done = FALSE; !Done; ) {
    444         Format += BytesPerFormatCharacter;
    445         FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
    446         switch (FormatCharacter) {
    447         case '.':
    448           Flags |= PRECISION;
    449           break;
    450         case '-':
    451           Flags |= LEFT_JUSTIFY;
    452           break;
    453         case '+':
    454           Flags |= PREFIX_SIGN;
    455           break;
    456         case ' ':
    457           Flags |= PREFIX_BLANK;
    458           break;
    459         case ',':
    460           Flags |= COMMA_TYPE;
    461           break;
    462         case 'L':
    463         case 'l':
    464           Flags |= LONG_TYPE;
    465           break;
    466         case '*':
    467           if ((Flags & PRECISION) == 0) {
    468             Flags |= PAD_TO_WIDTH;
    469             if (BaseListMarker == NULL) {
    470               Width = VA_ARG (VaListMarker, UINTN);
    471             } else {
    472               Width = BASE_ARG (BaseListMarker, UINTN);
    473             }
    474           } else {
    475             if (BaseListMarker == NULL) {
    476               Precision = VA_ARG (VaListMarker, UINTN);
    477             } else {
    478               Precision = BASE_ARG (BaseListMarker, UINTN);
    479             }
    480           }
    481           break;
    482         case '0':
    483           if ((Flags & PRECISION) == 0) {
    484             Flags |= PREFIX_ZERO;
    485           }
    486         case '1':
    487         case '2':
    488         case '3':
    489         case '4':
    490         case '5':
    491         case '6':
    492         case '7':
    493         case '8':
    494         case '9':
    495           for (Count = 0; ((FormatCharacter >= '0') &&  (FormatCharacter <= '9')); ){
    496             Count = (Count * 10) + FormatCharacter - '0';
    497             Format += BytesPerFormatCharacter;
    498             FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
    499           }
    500           Format -= BytesPerFormatCharacter;
    501           if ((Flags & PRECISION) == 0) {
    502             Flags |= PAD_TO_WIDTH;
    503             Width = Count;
    504           } else {
    505             Precision = Count;
    506           }
    507           break;
    508 
    509         case '\0':
    510           //
    511           // Make no output if Format string terminates unexpectedly when
    512           // looking up for flag, width, precision and type.
    513           //
    514           Format   -= BytesPerFormatCharacter;
    515           Precision = 0;
    516           //
    517           // break skipped on purpose.
    518           //
    519         default:
    520           Done = TRUE;
    521           break;
    522         }
    523       }
    524 
    525       //
    526       // Handle each argument type
    527       //
    528       switch (FormatCharacter) {
    529       case 'p':
    530         //
    531         // Flag space, +, 0, L & l are invalid for type p.
    532         //
    533         Flags &= ~((UINTN) (PREFIX_BLANK | PREFIX_SIGN | PREFIX_ZERO | LONG_TYPE));
    534         if (sizeof (VOID *) > 4) {
    535           Flags |= LONG_TYPE;
    536         }
    537         //
    538         // break skipped on purpose
    539         //
    540       case 'X':
    541         Flags |= PREFIX_ZERO;
    542         //
    543         // break skipped on purpose
    544         //
    545       case 'x':
    546         Flags |= RADIX_HEX;
    547         //
    548         // break skipped on purpose
    549         //
    550       case 'u':
    551         if ((Flags & RADIX_HEX) == 0) {
    552           Flags &= ~((UINTN) (PREFIX_SIGN));
    553           Flags |= UNSIGNED_TYPE;
    554         }
    555         //
    556         // break skipped on purpose
    557         //
    558       case 'd':
    559         if ((Flags & LONG_TYPE) == 0) {
    560           //
    561           // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
    562           // This assumption is made so the format string definition is compatible with the ANSI C
    563           // Specification for formatted strings.  It is recommended that the Base Types be used
    564           // everywhere, but in this one case, compliance with ANSI C is more important, and
    565           // provides an implementation that is compatible with that largest possible set of CPU
    566           // architectures.  This is why the type "int" is used in this one case.
    567           //
    568           if (BaseListMarker == NULL) {
    569             Value = VA_ARG (VaListMarker, int);
    570           } else {
    571             Value = BASE_ARG (BaseListMarker, int);
    572           }
    573         } else {
    574           if (BaseListMarker == NULL) {
    575             Value = VA_ARG (VaListMarker, INT64);
    576           } else {
    577             Value = BASE_ARG (BaseListMarker, INT64);
    578           }
    579         }
    580         if ((Flags & PREFIX_BLANK) != 0) {
    581           Prefix = ' ';
    582         }
    583         if ((Flags & PREFIX_SIGN) != 0) {
    584           Prefix = '+';
    585         }
    586         if ((Flags & COMMA_TYPE) != 0) {
    587           Comma = TRUE;
    588         }
    589         if ((Flags & RADIX_HEX) == 0) {
    590           Radix = 10;
    591           if (Comma) {
    592             Flags &= ~((UINTN) PREFIX_ZERO);
    593             Precision = 1;
    594           }
    595           if (Value < 0 && (Flags & UNSIGNED_TYPE) == 0) {
    596             Flags |= PREFIX_SIGN;
    597             Prefix = '-';
    598             Value = -Value;
    599           } else if ((Flags & UNSIGNED_TYPE) != 0 && (Flags & LONG_TYPE) == 0) {
    600             //
    601             // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
    602             // This assumption is made so the format string definition is compatible with the ANSI C
    603             // Specification for formatted strings.  It is recommended that the Base Types be used
    604             // everywhere, but in this one case, compliance with ANSI C is more important, and
    605             // provides an implementation that is compatible with that largest possible set of CPU
    606             // architectures.  This is why the type "unsigned int" is used in this one case.
    607             //
    608             Value = (unsigned int)Value;
    609           }
    610         } else {
    611           Radix = 16;
    612           Comma = FALSE;
    613           if ((Flags & LONG_TYPE) == 0 && Value < 0) {
    614             //
    615             // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
    616             // This assumption is made so the format string definition is compatible with the ANSI C
    617             // Specification for formatted strings.  It is recommended that the Base Types be used
    618             // everywhere, but in this one case, compliance with ANSI C is more important, and
    619             // provides an implementation that is compatible with that largest possible set of CPU
    620             // architectures.  This is why the type "unsigned int" is used in this one case.
    621             //
    622             Value = (unsigned int)Value;
    623           }
    624         }
    625         //
    626         // Convert Value to a reversed string
    627         //
    628         Count = BasePrintLibValueToString (ValueBuffer, Value, Radix) - ValueBuffer;
    629         if (Value == 0 && Precision == 0) {
    630           Count = 0;
    631         }
    632         ArgumentString = (CHAR8 *)ValueBuffer + Count;
    633 
    634         Digits = Count % 3;
    635         if (Digits != 0) {
    636           Digits = 3 - Digits;
    637         }
    638         if (Comma && Count != 0) {
    639           Count += ((Count - 1) / 3);
    640         }
    641         if (Prefix != 0) {
    642           Count++;
    643           Precision++;
    644         }
    645         Flags |= ARGUMENT_REVERSED;
    646         ZeroPad = TRUE;
    647         if ((Flags & PREFIX_ZERO) != 0) {
    648           if ((Flags & LEFT_JUSTIFY) == 0) {
    649             if ((Flags & PAD_TO_WIDTH) != 0) {
    650               if ((Flags & PRECISION) == 0) {
    651                 Precision = Width;
    652               }
    653             }
    654           }
    655         }
    656         break;
    657 
    658       case 's':
    659       case 'S':
    660         Flags |= ARGUMENT_UNICODE;
    661         //
    662         // break skipped on purpose
    663         //
    664       case 'a':
    665         if (BaseListMarker == NULL) {
    666           ArgumentString = VA_ARG (VaListMarker, CHAR8 *);
    667         } else {
    668           ArgumentString = BASE_ARG (BaseListMarker, CHAR8 *);
    669         }
    670         if (ArgumentString == NULL) {
    671           Flags &= ~((UINTN) ARGUMENT_UNICODE);
    672           ArgumentString = "<null string>";
    673         }
    674         //
    675         // Set the default precision for string to be zero if not specified.
    676         //
    677         if ((Flags & PRECISION) == 0) {
    678           Precision = 0;
    679         }
    680         break;
    681 
    682       case 'c':
    683         if (BaseListMarker == NULL) {
    684           Character = VA_ARG (VaListMarker, UINTN) & 0xffff;
    685         } else {
    686           Character = BASE_ARG (BaseListMarker, UINTN) & 0xffff;
    687         }
    688         ArgumentString = (CHAR8 *)&Character;
    689         Flags |= ARGUMENT_UNICODE;
    690         break;
    691 
    692       case 'g':
    693         if (BaseListMarker == NULL) {
    694           TmpGuid = VA_ARG (VaListMarker, GUID *);
    695         } else {
    696           TmpGuid = BASE_ARG (BaseListMarker, GUID *);
    697         }
    698         if (TmpGuid == NULL) {
    699           ArgumentString = "<null guid>";
    700         } else {
    701           GuidData1 = ReadUnaligned32 (&(TmpGuid->Data1));
    702           GuidData2 = ReadUnaligned16 (&(TmpGuid->Data2));
    703           GuidData3 = ReadUnaligned16 (&(TmpGuid->Data3));
    704           BasePrintLibSPrint (
    705             ValueBuffer,
    706             MAXIMUM_VALUE_CHARACTERS,
    707             0,
    708             "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
    709             GuidData1,
    710             GuidData2,
    711             GuidData3,
    712             TmpGuid->Data4[0],
    713             TmpGuid->Data4[1],
    714             TmpGuid->Data4[2],
    715             TmpGuid->Data4[3],
    716             TmpGuid->Data4[4],
    717             TmpGuid->Data4[5],
    718             TmpGuid->Data4[6],
    719             TmpGuid->Data4[7]
    720             );
    721           ArgumentString = ValueBuffer;
    722         }
    723         break;
    724 
    725       case 't':
    726         if (BaseListMarker == NULL) {
    727           TmpTime = VA_ARG (VaListMarker, TIME *);
    728         } else {
    729           TmpTime = BASE_ARG (BaseListMarker, TIME *);
    730         }
    731         if (TmpTime == NULL) {
    732           ArgumentString = "<null time>";
    733         } else {
    734           BasePrintLibSPrint (
    735             ValueBuffer,
    736             MAXIMUM_VALUE_CHARACTERS,
    737             0,
    738             "%02d/%02d/%04d  %02d:%02d",
    739             TmpTime->Month,
    740             TmpTime->Day,
    741             TmpTime->Year,
    742             TmpTime->Hour,
    743             TmpTime->Minute
    744             );
    745           ArgumentString = ValueBuffer;
    746         }
    747         break;
    748 
    749       case 'r':
    750         if (BaseListMarker == NULL) {
    751           Status = VA_ARG (VaListMarker, RETURN_STATUS);
    752         } else {
    753           Status = BASE_ARG (BaseListMarker, RETURN_STATUS);
    754         }
    755         ArgumentString = ValueBuffer;
    756         if (RETURN_ERROR (Status)) {
    757           //
    758           // Clear error bit
    759           //
    760           Index = Status & ~MAX_BIT;
    761           if (Index > 0 && Index <= ERROR_STATUS_NUMBER) {
    762             ArgumentString = mStatusString [Index + WARNING_STATUS_NUMBER];
    763           }
    764         } else {
    765           Index = Status;
    766           if (Index <= WARNING_STATUS_NUMBER) {
    767             ArgumentString = mStatusString [Index];
    768           }
    769         }
    770         if (ArgumentString == ValueBuffer) {
    771           BasePrintLibSPrint ((CHAR8 *) ValueBuffer, MAXIMUM_VALUE_CHARACTERS, 0, "%08X", Status);
    772         }
    773         break;
    774 
    775       case '\r':
    776         Format += BytesPerFormatCharacter;
    777         FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
    778         if (FormatCharacter == '\n') {
    779           //
    780           // Translate '\r\n' to '\r\n'
    781           //
    782           ArgumentString = "\r\n";
    783         } else {
    784           //
    785           // Translate '\r' to '\r'
    786           //
    787           ArgumentString = "\r";
    788           Format   -= BytesPerFormatCharacter;
    789         }
    790         break;
    791 
    792       case '\n':
    793         //
    794         // Translate '\n' to '\r\n' and '\n\r' to '\r\n'
    795         //
    796         ArgumentString = "\r\n";
    797         Format += BytesPerFormatCharacter;
    798         FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
    799         if (FormatCharacter != '\r') {
    800           Format   -= BytesPerFormatCharacter;
    801         }
    802         break;
    803 
    804       case '%':
    805       default:
    806         //
    807         // if the type is '%' or unknown, then print it to the screen
    808         //
    809         ArgumentString = (CHAR8 *)&FormatCharacter;
    810         Flags |= ARGUMENT_UNICODE;
    811         break;
    812       }
    813       break;
    814 
    815     case '\r':
    816       Format += BytesPerFormatCharacter;
    817       FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
    818       if (FormatCharacter == '\n') {
    819         //
    820         // Translate '\r\n' to '\r\n'
    821         //
    822         ArgumentString = "\r\n";
    823       } else {
    824         //
    825         // Translate '\r' to '\r'
    826         //
    827         ArgumentString = "\r";
    828         Format   -= BytesPerFormatCharacter;
    829       }
    830       break;
    831 
    832     case '\n':
    833       //
    834       // Translate '\n' to '\r\n' and '\n\r' to '\r\n'
    835       //
    836       ArgumentString = "\r\n";
    837       Format += BytesPerFormatCharacter;
    838       FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
    839       if (FormatCharacter != '\r') {
    840         Format   -= BytesPerFormatCharacter;
    841       }
    842       break;
    843 
    844     default:
    845       ArgumentString = (CHAR8 *)&FormatCharacter;
    846       Flags |= ARGUMENT_UNICODE;
    847       break;
    848     }
    849 
    850     //
    851     // Retrieve the ArgumentString attriubutes
    852     //
    853     if ((Flags & ARGUMENT_UNICODE) != 0) {
    854       ArgumentMask = 0xffff;
    855       BytesPerArgumentCharacter = 2;
    856     } else {
    857       ArgumentMask = 0xff;
    858       BytesPerArgumentCharacter = 1;
    859     }
    860     if ((Flags & ARGUMENT_REVERSED) != 0) {
    861       BytesPerArgumentCharacter = -BytesPerArgumentCharacter;
    862     } else {
    863       //
    864       // Compute the number of characters in ArgumentString and store it in Count
    865       // ArgumentString is either null-terminated, or it contains Precision characters
    866       //
    867       for (Count = 0; Count < Precision || ((Flags & PRECISION) == 0); Count++) {
    868         ArgumentCharacter = ((ArgumentString[Count * BytesPerArgumentCharacter] & 0xff) | ((ArgumentString[Count * BytesPerArgumentCharacter + 1]) << 8)) & ArgumentMask;
    869         if (ArgumentCharacter == 0) {
    870           break;
    871         }
    872       }
    873     }
    874 
    875     if (Precision < Count) {
    876       Precision = Count;
    877     }
    878 
    879     //
    880     // Pad before the string
    881     //
    882     if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH)) {
    883       LengthToReturn += ((Width - Precision) * BytesPerOutputCharacter);
    884       if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
    885         Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);
    886       }
    887     }
    888 
    889     if (ZeroPad) {
    890       if (Prefix != 0) {
    891         LengthToReturn += (1 * BytesPerOutputCharacter);
    892         if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
    893           Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);
    894         }
    895       }
    896       LengthToReturn += ((Precision - Count) * BytesPerOutputCharacter);
    897       if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
    898         Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, '0', BytesPerOutputCharacter);
    899       }
    900     } else {
    901       LengthToReturn += ((Precision - Count) * BytesPerOutputCharacter);
    902       if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
    903         Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, ' ', BytesPerOutputCharacter);
    904       }
    905       if (Prefix != 0) {
    906         LengthToReturn += (1 * BytesPerOutputCharacter);
    907         if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
    908           Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);
    909         }
    910       }
    911     }
    912 
    913     //
    914     // Output the Prefix character if it is present
    915     //
    916     Index = 0;
    917     if (Prefix != 0) {
    918       Index++;
    919     }
    920 
    921     //
    922     // Copy the string into the output buffer performing the required type conversions
    923     //
    924     while (Index < Count) {
    925       ArgumentCharacter = ((*ArgumentString & 0xff) | (*(ArgumentString + 1) << 8)) & ArgumentMask;
    926 
    927       LengthToReturn += (1 * BytesPerOutputCharacter);
    928       if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
    929         Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ArgumentCharacter, BytesPerOutputCharacter);
    930       }
    931       ArgumentString    += BytesPerArgumentCharacter;
    932       Index++;
    933       if (Comma) {
    934         Digits++;
    935         if (Digits == 3) {
    936           Digits = 0;
    937           Index++;
    938           if (Index < Count) {
    939             LengthToReturn += (1 * BytesPerOutputCharacter);
    940             if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
    941               Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', BytesPerOutputCharacter);
    942             }
    943           }
    944         }
    945       }
    946     }
    947 
    948     //
    949     // Pad after the string
    950     //
    951     if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH | LEFT_JUSTIFY)) {
    952       LengthToReturn += ((Width - Precision) * BytesPerOutputCharacter);
    953       if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
    954         Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);
    955       }
    956     }
    957 
    958     //
    959     // Get the next character from the format string
    960     //
    961     Format += BytesPerFormatCharacter;
    962 
    963     //
    964     // Get the next character from the format string
    965     //
    966     FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
    967   }
    968 
    969   if ((Flags & COUNT_ONLY_NO_PRINT) != 0) {
    970     return (LengthToReturn / BytesPerOutputCharacter);
    971   }
    972 
    973   ASSERT (Buffer != NULL);
    974   //
    975   // Null terminate the Unicode or ASCII string
    976   //
    977   BasePrintLibFillBuffer (Buffer, EndBuffer + BytesPerOutputCharacter, 1, 0, BytesPerOutputCharacter);
    978   //
    979   // Make sure output buffer cannot contain more than PcdMaximumUnicodeStringLength
    980   // Unicode characters if PcdMaximumUnicodeStringLength is not zero.
    981   //
    982   ASSERT ((((Flags & OUTPUT_UNICODE) == 0)) || (StrSize ((CHAR16 *) OriginalBuffer) != 0));
    983   //
    984   // Make sure output buffer cannot contain more than PcdMaximumAsciiStringLength
    985   // ASCII characters if PcdMaximumAsciiStringLength is not zero.
    986   //
    987   ASSERT ((((Flags & OUTPUT_UNICODE) != 0)) || (AsciiStrSize (OriginalBuffer) != 0));
    988 
    989   return ((Buffer - OriginalBuffer) / BytesPerOutputCharacter);
    990 }
    991 
    992 /**
    993   Worker function that produces a Null-terminated string in an output buffer
    994   based on a Null-terminated format string and variable argument list.
    995 
    996   VSPrint function to process format and place the results in Buffer. Since a
    997   VA_LIST is used this routine allows the nesting of Vararg routines. Thus
    998   this is the main print working routine
    999 
   1000   @param  StartOfBuffer The character buffer to print the results of the parsing
   1001                         of Format into.
   1002   @param  BufferSize    The maximum number of characters to put into buffer.
   1003                         Zero means no limit.
   1004   @param  Flags         Initial flags value.
   1005                         Can only have FORMAT_UNICODE and OUTPUT_UNICODE set
   1006   @param  FormatString  A Null-terminated format string.
   1007   @param  ...           The variable argument list.
   1008 
   1009   @return The number of characters printed.
   1010 
   1011 **/
   1012 UINTN
   1013 EFIAPI
   1014 BasePrintLibSPrint (
   1015   OUT CHAR8        *StartOfBuffer,
   1016   IN  UINTN        BufferSize,
   1017   IN  UINTN        Flags,
   1018   IN  CONST CHAR8  *FormatString,
   1019   ...
   1020   )
   1021 {
   1022   VA_LIST  Marker;
   1023   UINTN    NumberOfPrinted;
   1024 
   1025   VA_START (Marker, FormatString);
   1026   NumberOfPrinted = BasePrintLibSPrintMarker (StartOfBuffer, BufferSize, Flags, FormatString, Marker, NULL);
   1027   VA_END (Marker);
   1028   return NumberOfPrinted;
   1029 }
   1030