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