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