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