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