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