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