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