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
20GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
21
22GLOBAL_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**/
81CHAR8 *
82BasePrintLibFillBuffer (
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**/
115CHAR8 *
116BasePrintLibValueToString (
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**/
177UINTN
178BasePrintLibConvertValueToString (
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**/
308UINTN
309BasePrintLibSPrintMarker (
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**/
1012UINTN
1013EFIAPI
1014BasePrintLibSPrint (
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