VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePrintLib/PrintLibInternal.c

最後變更 在這個檔案是 101291,由 vboxsync 提交於 14 月 前

EFI/FirmwareNew: Make edk2-stable202308 build on all supported platforms (using gcc at least, msvc not tested yet), bugref:4643

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette