]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BasePrintLib/PrintLibInternal.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdePkg / Library / BasePrintLib / PrintLibInternal.c
CommitLineData
e1f414b6 1/** @file\r
eceb3a4c 2 Print Library internal worker functions.\r
e1f414b6 3\r
9095d37b 4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
9344f092 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
e1f414b6 6\r
e1f414b6 7**/\r
8\r
e1f414b6 9#include "PrintLibInternal.h"\r
10\r
2f88bd3a
MK
11#define WARNING_STATUS_NUMBER 5\r
12#define ERROR_STATUS_NUMBER 33\r
e389c39b 13\r
9b002aa4
HW
14//\r
15// Safe print checks\r
16//\r
2f88bd3a
MK
17#define RSIZE_MAX (PcdGet32 (PcdMaximumUnicodeStringLength))\r
18#define ASCII_RSIZE_MAX (PcdGet32 (PcdMaximumAsciiStringLength))\r
9b002aa4
HW
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
2f88bd3a 28GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexStr[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };\r
e1f414b6 29\r
a2433243
AB
30//\r
31// Longest string: RETURN_WARN_BUFFER_TOO_SMALL => 24 characters plus NUL byte\r
32//\r
2f88bd3a 33GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mWarningString[][24+1] = {\r
e389c39b 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
0df625fa 39 "Warning Stale Data", // RETURN_WARN_STALE_DATA = 5\r
a2433243
AB
40};\r
41\r
42//\r
43// Longest string: RETURN_INCOMPATIBLE_VERSION => 20 characters plus NUL byte\r
44//\r
2f88bd3a 45GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mErrorString[][20+1] = {\r
e389c39b 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
5e2fd937 69 "Protocol Error", // RETURN_PROTOCOL_ERROR = 24 | MAX_BIT\r
0df625fa
LG
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
e389c39b 79};\r
80\r
e1f414b6 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
2fc59a00 86 @param Buffer The buffer to place the Unicode or ASCII string.\r
e1f414b6 87 @param EndBuffer The end of the input Buffer. No characters will be\r
9095d37b 88 placed after that.\r
2fc59a00 89 @param Length The count of character to be placed into Buffer.\r
a2bc29c4 90 (Negative value indicates no buffer fill.)\r
2fc59a00 91 @param Character The character to be placed into Buffer.\r
92 @param Increment The character increment in Buffer.\r
e1f414b6 93\r
2fc59a00 94 @return Buffer.\r
e1f414b6 95\r
96**/\r
97CHAR8 *\r
98BasePrintLibFillBuffer (\r
2f88bd3a
MK
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
e1f414b6 104 )\r
105{\r
a2bc29c4 106 INTN Index;\r
9095d37b 107\r
a2bc29c4 108 for (Index = 0; Index < Length && Buffer < EndBuffer; Index++) {\r
2f88bd3a 109 *Buffer = (CHAR8)Character;\r
a2bc29c4 110 if (Increment != 1) {\r
111 *(Buffer + 1) = (CHAR8)(Character >> 8);\r
112 }\r
2f88bd3a 113\r
a2bc29c4 114 Buffer += Increment;\r
115 }\r
116\r
117 return Buffer;\r
e1f414b6 118}\r
119\r
120/**\r
7c905091 121 Internal function that convert a number to a string in Buffer.\r
e1f414b6 122\r
7c905091 123 Print worker function that converts a decimal or hexadecimal number to an ASCII string in Buffer.\r
e1f414b6 124\r
7c905091 125 @param Buffer Location to place the ASCII string of Value.\r
2fc59a00 126 @param Value The value to convert to a Decimal or Hexadecimal string in Buffer.\r
e1f414b6 127 @param Radix Radix of the value\r
128\r
7c905091 129 @return A pointer to the end of buffer filled with ASCII string.\r
e1f414b6 130\r
131**/\r
7c905091 132CHAR8 *\r
e1f414b6 133BasePrintLibValueToString (\r
9095d37b
LG
134 IN OUT CHAR8 *Buffer,\r
135 IN INT64 Value,\r
e1f414b6 136 IN UINTN Radix\r
137 )\r
138{\r
e1f414b6 139 UINT32 Remainder;\r
140\r
141 //\r
142 // Loop to convert one digit at a time in reverse order\r
143 //\r
7c905091 144 *Buffer = 0;\r
e1f414b6 145 do {\r
2f88bd3a 146 Value = (INT64)DivU64x32Remainder ((UINT64)Value, (UINT32)Radix, &Remainder);\r
7c905091 147 *(++Buffer) = mHexStr[Remainder];\r
e1f414b6 148 } while (Value != 0);\r
eceb3a4c
LG
149\r
150 //\r
7c905091 151 // Return pointer of the end of filled buffer.\r
eceb3a4c 152 //\r
7c905091 153 return Buffer;\r
e1f414b6 154}\r
155\r
156/**\r
157 Internal function that converts a decimal value to a Null-terminated string.\r
9095d37b
LG
158\r
159 Converts the decimal number specified by Value to a Null-terminated\r
e1f414b6 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
efb23117 162 The total number of characters placed in Buffer is returned.\r
e1f414b6 163 If the conversion contains more than Width characters, then only the first\r
9095d37b 164 Width characters are returned, and the total number of characters\r
e1f414b6 165 required to perform the conversion is returned.\r
9095d37b 166 Additional conversion parameters are specified in Flags.\r
e1f414b6 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
efb23117 172 If Value is < 0, then the fist character in Buffer is a '-'.\r
9095d37b
LG
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
e1f414b6 175 sign character, '0' characters, digit characters for Value, and the Null-terminator\r
176 add up to Width characters.\r
e1f414b6 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
2fc59a00 182 @param Buffer The pointer to the output buffer for the produced Null-terminated\r
e1f414b6 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
2fc59a00 189 @param Increment The character increment in Buffer.\r
9095d37b 190\r
efb23117 191 @return Total number of characters required to perform the conversion.\r
e1f414b6 192\r
193**/\r
194UINTN\r
195BasePrintLibConvertValueToString (\r
2f88bd3a
MK
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
e1f414b6 201 )\r
202{\r
203 CHAR8 *OriginalBuffer;\r
204 CHAR8 *EndBuffer;\r
205 CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];\r
7c905091 206 CHAR8 *ValueBufferPtr;\r
e1f414b6 207 UINTN Count;\r
208 UINTN Digits;\r
209 UINTN Index;\r
210 UINTN Radix;\r
211\r
eceb3a4c
LG
212 //\r
213 // Make sure Buffer is not NULL and Width < MAXIMUM\r
214 //\r
e1f414b6 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
df8d0595 223 // If both COMMA_TYPE and RADIX_HEX are set, then ASSERT ()\r
e1f414b6 224 //\r
841c0770 225 ASSERT (((Flags & COMMA_TYPE) == 0) || ((Flags & RADIX_HEX) == 0));\r
e1f414b6 226\r
227 OriginalBuffer = Buffer;\r
9095d37b 228\r
eceb3a4c
LG
229 //\r
230 // Width is 0 or COMMA_TYPE is set, PREFIX_ZERO is ignored.\r
231 //\r
2f88bd3a
MK
232 if ((Width == 0) || ((Flags & COMMA_TYPE) != 0)) {\r
233 Flags &= ~((UINTN)PREFIX_ZERO);\r
e1f414b6 234 }\r
2f88bd3a 235\r
eceb3a4c
LG
236 //\r
237 // If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.\r
238 //\r
e1f414b6 239 if (Width == 0) {\r
240 Width = MAXIMUM_VALUE_CHARACTERS - 1;\r
241 }\r
2f88bd3a 242\r
e1f414b6 243 //\r
244 // Set the tag for the end of the input Buffer.\r
245 //\r
246 EndBuffer = Buffer + Width * Increment;\r
9095d37b 247\r
eceb3a4c
LG
248 //\r
249 // Convert decimal negative\r
250 //\r
e1f414b6 251 if ((Value < 0) && ((Flags & RADIX_HEX) == 0)) {\r
2f88bd3a 252 Value = -Value;\r
e1f414b6 253 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, '-', Increment);\r
254 Width--;\r
255 }\r
9095d37b 256\r
eceb3a4c
LG
257 //\r
258 // Count the length of the value string.\r
259 //\r
2f88bd3a 260 Radix = ((Flags & RADIX_HEX) == 0) ? 10 : 16;\r
7c905091 261 ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, Value, Radix);\r
2f88bd3a 262 Count = ValueBufferPtr - ValueBuffer;\r
9095d37b 263\r
eceb3a4c
LG
264 //\r
265 // Append Zero\r
266 //\r
e1f414b6 267 if ((Flags & PREFIX_ZERO) != 0) {\r
268 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Count, '0', Increment);\r
269 }\r
9095d37b 270\r
eceb3a4c
LG
271 //\r
272 // Print Comma type for every 3 characters\r
273 //\r
e1f414b6 274 Digits = Count % 3;\r
275 if (Digits != 0) {\r
276 Digits = 3 - Digits;\r
277 }\r
2f88bd3a 278\r
e1f414b6 279 for (Index = 0; Index < Count; Index++) {\r
7c905091 280 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, *ValueBufferPtr--, Increment);\r
e1f414b6 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
9095d37b 291\r
eceb3a4c
LG
292 //\r
293 // Print Null-terminator\r
294 //\r
e1f414b6 295 BasePrintLibFillBuffer (Buffer, EndBuffer + Increment, 1, 0, Increment);\r
296\r
297 return ((Buffer - OriginalBuffer) / Increment);\r
298}\r
299\r
51f0ceb4
HW
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
2f88bd3a
MK
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
51f0ceb4
HW
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
2f88bd3a
MK
409 if ((Width == 0) || ((Flags & COMMA_TYPE) != 0)) {\r
410 Flags &= ~((UINTN)PREFIX_ZERO);\r
51f0ceb4 411 }\r
2f88bd3a 412\r
51f0ceb4
HW
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
2f88bd3a 424 Radix = ((Flags & RADIX_HEX) == 0) ? 10 : 16;\r
51f0ceb4
HW
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
2f88bd3a 435\r
51f0ceb4
HW
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
2f88bd3a 460 Value = -Value;\r
51f0ceb4
HW
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
2f88bd3a 469 Count = ValueBufferPtr - ValueBuffer;\r
51f0ceb4
HW
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
2f88bd3a 485\r
51f0ceb4
HW
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
e389c39b 507/**\r
9095d37b 508 Worker function that produces a Null-terminated string in an output buffer\r
e389c39b 509 based on a Null-terminated format string and a VA_LIST argument list.\r
510\r
9095d37b
LG
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
e389c39b 513 this is the main print working routine.\r
514\r
f405c067 515 If COUNT_ONLY_NO_PRINT is set in Flags, Buffer will not be modified at all.\r
516\r
9095d37b 517 @param[out] Buffer The character buffer to print the results of the\r
f405c067 518 parsing of Format into.\r
9095d37b 519 @param[in] BufferSize The maximum number of characters to put into\r
f405c067 520 buffer.\r
521 @param[in] Flags Initial flags value.\r
9095d37b 522 Can only have FORMAT_UNICODE, OUTPUT_UNICODE,\r
f405c067 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
e389c39b 529\r
2fc59a00 530 @return The number of characters printed not including the Null-terminator.\r
f405c067 531 If COUNT_ONLY_NO_PRINT was set returns the same, but without any\r
532 modification to Buffer.\r
e389c39b 533\r
534**/\r
535UINTN\r
2075236e 536BasePrintLibSPrintMarker (\r
e389c39b 537 OUT CHAR8 *Buffer,\r
538 IN UINTN BufferSize,\r
539 IN UINTN Flags,\r
540 IN CONST CHAR8 *Format,\r
d0e2f823 541 IN VA_LIST VaListMarker OPTIONAL,\r
2075236e 542 IN BASE_LIST BaseListMarker OPTIONAL\r
e389c39b 543 )\r
544{\r
2f88bd3a
MK
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
e389c39b 575\r
f405c067 576 //\r
577 // If you change this code be sure to match the 2 versions of this function.\r
9095d37b 578 // Nearly identical logic is found in the BasePrintLib and\r
f405c067 579 // DxePrintLibPrint2Protocol (both PrintLib instances).\r
580 //\r
581\r
9b002aa4
HW
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
2f88bd3a 606\r
9b002aa4
HW
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
2f88bd3a 612\r
9b002aa4
HW
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
2f88bd3a 624\r
9b002aa4 625 BytesPerFormatCharacter = 2;\r
2f88bd3a 626 FormatMask = 0xffff;\r
9b002aa4
HW
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
2f88bd3a 631\r
9b002aa4 632 BytesPerFormatCharacter = 1;\r
2f88bd3a 633 FormatMask = 0xff;\r
9b002aa4
HW
634 }\r
635\r
83f1f16a 636 if ((Flags & COUNT_ONLY_NO_PRINT) != 0) {\r
f405c067 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
e389c39b 647 }\r
648\r
f405c067 649 LengthToReturn = 0;\r
2f88bd3a 650 EndBuffer = NULL;\r
28087ef0 651 OriginalBuffer = NULL;\r
f405c067 652\r
e389c39b 653 //\r
654 // Reserve space for the Null terminator.\r
655 //\r
28087ef0
HL
656 if (Buffer != NULL) {\r
657 BufferSize--;\r
658 OriginalBuffer = Buffer;\r
2075236e 659\r
28087ef0
HL
660 //\r
661 // Set the tag for the end of the input Buffer.\r
662 //\r
663 EndBuffer = Buffer + BufferSize * BytesPerOutputCharacter;\r
664 }\r
e389c39b 665\r
e389c39b 666 //\r
667 // Get the first character from the format string\r
668 //\r
b1d4b965 669 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
e389c39b 670\r
671 //\r
672 // Loop until the end of the format string is reached or the output buffer is full\r
673 //\r
28087ef0
HL
674 while (FormatCharacter != 0) {\r
675 if ((Buffer != NULL) && (Buffer >= EndBuffer)) {\r
676 break;\r
677 }\r
2f88bd3a 678\r
e389c39b 679 //\r
680 // Clear all the flag bits except those that may have been passed in\r
681 //\r
2f88bd3a 682 Flags &= (UINTN)(OUTPUT_UNICODE | FORMAT_UNICODE | COUNT_ONLY_NO_PRINT);\r
e389c39b 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
2f88bd3a
MK
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
e389c39b 789 switch (FormatCharacter) {\r
2f88bd3a
MK
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
2075236e 797 }\r
9095d37b 798\r
e389c39b 799 //\r
2f88bd3a
MK
800 // break skipped on purpose\r
801 //\r
802 case 'X':\r
803 Flags |= PREFIX_ZERO;\r
e389c39b 804 //\r
2f88bd3a 805 // break skipped on purpose\r
e389c39b 806 //\r
2f88bd3a
MK
807 case 'x':\r
808 Flags |= RADIX_HEX;\r
e389c39b 809 //\r
2f88bd3a
MK
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
e389c39b 817\r
57dd2382 818 //\r
2f88bd3a 819 // break skipped on purpose\r
57dd2382 820 //\r
2f88bd3a
MK
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
9ade4339 894 //\r
2f88bd3a 895 // Convert Value to a reversed string\r
9ade4339 896 //\r
2f88bd3a
MK
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
57dd2382 950 //\r
2f88bd3a 951 // Set the default precision for string to be zero if not specified.\r
57dd2382 952 //\r
2f88bd3a
MK
953 if ((Flags & PRECISION) == 0) {\r
954 Precision = 0;\r
955 }\r
9095d37b 956\r
2f88bd3a
MK
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
e389c39b 1051 }\r
1052 }\r
e389c39b 1053\r
2f88bd3a
MK
1054 if (ArgumentString == ValueBuffer) {\r
1055 BasePrintLibSPrint ((CHAR8 *)ValueBuffer, MAXIMUM_VALUE_CHARACTERS, 0, "%08X", Status);\r
1056 }\r
e389c39b 1057\r
2f88bd3a 1058 break;\r
e389c39b 1059\r
2f88bd3a
MK
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
e389c39b 1075\r
2f88bd3a 1076 break;\r
e389c39b 1077\r
2f88bd3a
MK
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
e389c39b 1099 }\r
2f88bd3a 1100\r
e389c39b 1101 break;\r
1102\r
c553db4b 1103 case '\r':\r
2f88bd3a 1104 Format += BytesPerFormatCharacter;\r
b1d4b965 1105 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
c553db4b 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
2f88bd3a 1116 Format -= BytesPerFormatCharacter;\r
c553db4b 1117 }\r
2f88bd3a 1118\r
c553db4b 1119 break;\r
1120\r
e389c39b 1121 case '\n':\r
c553db4b 1122 //\r
1123 // Translate '\n' to '\r\n' and '\n\r' to '\r\n'\r
1124 //\r
2f88bd3a
MK
1125 ArgumentString = "\r\n";\r
1126 Format += BytesPerFormatCharacter;\r
b1d4b965 1127 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
c553db4b 1128 if (FormatCharacter != '\r') {\r
2f88bd3a 1129 Format -= BytesPerFormatCharacter;\r
c553db4b 1130 }\r
2f88bd3a 1131\r
e389c39b 1132 break;\r
1133\r
e389c39b 1134 default:\r
e389c39b 1135 ArgumentString = (CHAR8 *)&FormatCharacter;\r
2f88bd3a 1136 Flags |= ARGUMENT_UNICODE;\r
e389c39b 1137 break;\r
e389c39b 1138 }\r
1139\r
1140 //\r
1141 // Retrieve the ArgumentString attriubutes\r
1142 //\r
1143 if ((Flags & ARGUMENT_UNICODE) != 0) {\r
2f88bd3a 1144 ArgumentMask = 0xffff;\r
e389c39b 1145 BytesPerArgumentCharacter = 2;\r
1146 } else {\r
2f88bd3a 1147 ArgumentMask = 0xff;\r
e389c39b 1148 BytesPerArgumentCharacter = 1;\r
1149 }\r
2f88bd3a 1150\r
e389c39b 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
6805854a 1158 for (Count = 0;\r
2f88bd3a
MK
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
e389c39b 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
6bae492f 1180 LengthToReturn += ((Width - Precision) * BytesPerOutputCharacter);\r
2f88bd3a 1181 if (((Flags & COUNT_ONLY_NO_PRINT) == 0) && (Buffer != NULL)) {\r
f405c067 1182 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);\r
1183 }\r
e389c39b 1184 }\r
1185\r
1186 if (ZeroPad) {\r
1187 if (Prefix != 0) {\r
6bae492f 1188 LengthToReturn += (1 * BytesPerOutputCharacter);\r
2f88bd3a 1189 if (((Flags & COUNT_ONLY_NO_PRINT) == 0) && (Buffer != NULL)) {\r
f405c067 1190 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);\r
1191 }\r
1192 }\r
2f88bd3a 1193\r
6bae492f 1194 LengthToReturn += ((Precision - Count) * BytesPerOutputCharacter);\r
2f88bd3a 1195 if (((Flags & COUNT_ONLY_NO_PRINT) == 0) && (Buffer != NULL)) {\r
f405c067 1196 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, '0', BytesPerOutputCharacter);\r
e389c39b 1197 }\r
e389c39b 1198 } else {\r
6bae492f 1199 LengthToReturn += ((Precision - Count) * BytesPerOutputCharacter);\r
2f88bd3a 1200 if (((Flags & COUNT_ONLY_NO_PRINT) == 0) && (Buffer != NULL)) {\r
f405c067 1201 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, ' ', BytesPerOutputCharacter);\r
1202 }\r
2f88bd3a 1203\r
e389c39b 1204 if (Prefix != 0) {\r
6bae492f 1205 LengthToReturn += (1 * BytesPerOutputCharacter);\r
2f88bd3a 1206 if (((Flags & COUNT_ONLY_NO_PRINT) == 0) && (Buffer != NULL)) {\r
f405c067 1207 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);\r
1208 }\r
e389c39b 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
701e8cc2
WJ
1223 while (Index < Count &&\r
1224 (ArgumentString[0] != '\0' ||\r
2f88bd3a
MK
1225 (BytesPerArgumentCharacter > 1 && ArgumentString[1] != '\0')))\r
1226 {\r
ea0b1506 1227 ArgumentCharacter = ((*ArgumentString & 0xff) | (((UINT8)*(ArgumentString + 1)) << 8)) & ArgumentMask;\r
e389c39b 1228\r
6bae492f 1229 LengthToReturn += (1 * BytesPerOutputCharacter);\r
2f88bd3a 1230 if (((Flags & COUNT_ONLY_NO_PRINT) == 0) && (Buffer != NULL)) {\r
f405c067 1231 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ArgumentCharacter, BytesPerOutputCharacter);\r
1232 }\r
2f88bd3a
MK
1233\r
1234 ArgumentString += BytesPerArgumentCharacter;\r
e389c39b 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
6bae492f 1242 LengthToReturn += (1 * BytesPerOutputCharacter);\r
2f88bd3a 1243 if (((Flags & COUNT_ONLY_NO_PRINT) == 0) && (Buffer != NULL)) {\r
f405c067 1244 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', BytesPerOutputCharacter);\r
1245 }\r
e389c39b 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
6bae492f 1255 LengthToReturn += ((Width - Precision) * BytesPerOutputCharacter);\r
2f88bd3a 1256 if (((Flags & COUNT_ONLY_NO_PRINT) == 0) && (Buffer != NULL)) {\r
f405c067 1257 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);\r
1258 }\r
e389c39b 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
b1d4b965 1269 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
e389c39b 1270 }\r
1271\r
4ae2e63c 1272 if ((Flags & COUNT_ONLY_NO_PRINT) != 0) {\r
f405c067 1273 return (LengthToReturn / BytesPerOutputCharacter);\r
1274 }\r
1275\r
6709bbd1 1276 ASSERT (Buffer != NULL);\r
e389c39b 1277 //\r
1278 // Null terminate the Unicode or ASCII string\r
1279 //\r
1280 BasePrintLibFillBuffer (Buffer, EndBuffer + BytesPerOutputCharacter, 1, 0, BytesPerOutputCharacter);\r
e389c39b 1281\r
1282 return ((Buffer - OriginalBuffer) / BytesPerOutputCharacter);\r
1283}\r
1284\r
1285/**\r
9095d37b 1286 Worker function that produces a Null-terminated string in an output buffer\r
e389c39b 1287 based on a Null-terminated format string and variable argument list.\r
1288\r
9095d37b
LG
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
efb23117 1291 this is the main print working routine\r
e389c39b 1292\r
2fc59a00 1293 @param StartOfBuffer The character buffer to print the results of the parsing\r
e389c39b 1294 of Format into.\r
2fc59a00 1295 @param BufferSize The maximum number of characters to put into buffer.\r
e389c39b 1296 Zero means no limit.\r
7c905091 1297 @param Flags Initial flags value.\r
e389c39b 1298 Can only have FORMAT_UNICODE and OUTPUT_UNICODE set\r
2fc59a00 1299 @param FormatString A Null-terminated format string.\r
e389c39b 1300 @param ... The variable argument list.\r
1301\r
2fc59a00 1302 @return The number of characters printed.\r
e389c39b 1303\r
1304**/\r
1305UINTN\r
932d66a9 1306EFIAPI\r
e389c39b 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
3bbe68a3 1316 UINTN NumberOfPrinted;\r
e389c39b 1317\r
1318 VA_START (Marker, FormatString);\r
3bbe68a3 1319 NumberOfPrinted = BasePrintLibSPrintMarker (StartOfBuffer, BufferSize, Flags, FormatString, Marker, NULL);\r
1320 VA_END (Marker);\r
1321 return NumberOfPrinted;\r
e389c39b 1322}\r