]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Foundation/Library/Dxe/Print/Print.c
EdkCompatabilityPkg: Fix build issues with X64 clang
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / Dxe / Print / Print.c
CommitLineData
3eb9473e 1/*++\r
2\r
4ea9375a
HT
3Copyright (c) 2004 - 2007, Intel Corporation. All rights reserved.<BR>\r
4This program and the accompanying materials \r
3eb9473e 5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 Print.c\r
15\r
16Abstract:\r
17\r
18 Basic Ascii AvSPrintf() function named VSPrint(). VSPrint() enables very\r
19 simple implemenation of SPrint() and Print() to support debug. \r
20\r
21 You can not Print more than EFI_DRIVER_LIB_MAX_PRINT_BUFFER characters at a \r
22 time. This makes the implementation very simple.\r
23\r
24 VSPrint, Print, SPrint format specification has the follwoing form\r
25\r
26 %[flags][width]type\r
27\r
28 flags:\r
29 '-' - Left justify\r
30 '+' - Prefix a sign\r
31 ' ' - Prefix a blank\r
32 ',' - Place commas in numberss\r
33 '0' - Prefix for width with zeros\r
34 'l' - UINT64\r
35 'L' - UINT64\r
36\r
37 width:\r
38 '*' - Get width from a UINTN argumnet from the argument list\r
39 Decimal number that represents width of print\r
40\r
41 type:\r
0f77dfb6 42 'p' - arugment is VOID *; printed as hex number\r
3eb9473e 43 'X' - argument is a UINTN hex number, prefix '0'\r
44 'x' - argument is a hex number\r
45 'd' - argument is a decimal number\r
46 'a' - argument is an ascii string \r
47 'S','s' - argument is an Unicode string\r
48 'g' - argument is a pointer to an EFI_GUID\r
49 't' - argument is a pointer to an EFI_TIME structure\r
50 'c' - argument is an ascii character\r
51 'r' - argument is EFI_STATUS\r
52 '%' - Print a %\r
53\r
54--*/\r
55\r
56#include "TianoCommon.h"\r
57#include "EfiCommonLib.h"\r
58#include "PrintWidth.h"\r
59#include "EfiPrintLib.h"\r
60#include "Print.h"\r
61\r
62\r
3eb9473e 63STATIC\r
64UINTN\r
65GuidToString (\r
66 IN EFI_GUID *Guid,\r
67 IN OUT CHAR_W *Buffer,\r
68 IN UINTN BufferSize\r
69 );\r
70\r
71STATIC\r
72UINTN\r
73TimeToString (\r
74 IN EFI_TIME *Time,\r
75 IN OUT CHAR_W *Buffer,\r
76 IN UINTN BufferSize\r
77 );\r
78\r
79STATIC\r
80UINTN\r
81EfiStatusToString (\r
82 IN EFI_STATUS Status,\r
83 OUT CHAR_W *Buffer,\r
84 IN UINTN BufferSize\r
85 );\r
86\r
87UINTN\r
88SPrint (\r
89 OUT CHAR_W *Buffer,\r
90 IN UINTN BufferSize,\r
91 IN CONST CHAR_W *Format,\r
92 ...\r
93 )\r
94/*++\r
95\r
96Routine Description:\r
97\r
98 SPrint function to process format and place the results in Buffer.\r
99\r
100Arguments:\r
101\r
102 Buffer - Wide char buffer to print the results of the parsing of Format into.\r
103\r
104 BufferSize - Maximum number of characters to put into buffer. Zero means no \r
105 limit.\r
106\r
107 Format - Format string see file header for more details.\r
108\r
109 ... - Vararg list consumed by processing Format.\r
110\r
111Returns: \r
112\r
113 Number of characters printed.\r
114\r
115--*/\r
116{\r
117 UINTN Return;\r
118 VA_LIST Marker;\r
119\r
120 VA_START (Marker, Format);\r
121 Return = VSPrint (Buffer, BufferSize, Format, Marker);\r
122 VA_END (Marker);\r
123 \r
124 return Return;\r
125}\r
126\r
127\r
128UINTN\r
c7f33ca4 129EFIAPI\r
3eb9473e 130VSPrint (\r
131 OUT CHAR_W *StartOfBuffer,\r
132 IN UINTN BufferSize,\r
133 IN CONST CHAR_W *FormatString,\r
134 IN VA_LIST Marker\r
135 )\r
136/*++\r
137\r
138Routine Description:\r
139\r
140 VSPrint function to process format and place the results in Buffer. Since a \r
141 VA_LIST is used this rountine allows the nesting of Vararg routines. Thus \r
142 this is the main print working routine\r
143\r
144Arguments:\r
145\r
146 StartOfBuffer - Unicode buffer to print the results of the parsing of Format into.\r
147\r
148 BufferSize - Maximum number of characters to put into buffer. Zero means \r
149 no limit.\r
150\r
151 FormatString - Unicode format string see file header for more details.\r
152\r
153 Marker - Vararg list consumed by processing Format.\r
154\r
155Returns: \r
156\r
157 Number of characters printed.\r
158\r
159--*/\r
160{\r
161 CHAR16 TempBuffer[CHARACTER_NUMBER_FOR_VALUE];\r
162 CHAR_W *Buffer;\r
163 CHAR8 *AsciiStr;\r
164 CHAR16 *UnicodeStr;\r
165 CHAR_W *Format;\r
166 UINTN Index;\r
167 UINTN Flags;\r
168 UINTN Width;\r
169 UINTN Count;\r
170 UINTN NumberOfCharacters;\r
171 UINTN BufferLeft;\r
172 UINT64 Value;\r
173 EFI_GUID *TmpGUID;\r
271d2c7f 174 BOOLEAN Done;\r
3eb9473e 175\r
176 //\r
177 // Process the format string. Stop if Buffer is over run.\r
178 //\r
179\r
180 Buffer = StartOfBuffer;\r
181 Format = (CHAR_W *)FormatString; \r
182 NumberOfCharacters = BufferSize/sizeof(CHAR_W);\r
183 BufferLeft = BufferSize;\r
184 for (Index = 0; (*Format != '\0') && (Index < NumberOfCharacters - 1); Format++) {\r
185 if (*Format != '%') {\r
186 if ((*Format == '\n') && (Index < NumberOfCharacters - 2)) { \r
187 //\r
188 // If carage return add line feed\r
189 //\r
190 Buffer[Index++] = '\r';\r
191 BufferLeft -= sizeof(CHAR_W);\r
192 }\r
193 Buffer[Index++] = *Format;\r
194 BufferLeft -= sizeof(CHAR_W);\r
195 } else {\r
196 \r
197 //\r
198 // Now it's time to parse what follows after %\r
271d2c7f 199 // \r
200 Flags = 0;\r
201 Width = 0;\r
202 for (Done = FALSE; !Done; ) {\r
203 Format++;\r
204 \r
205 switch (*Format) {\r
206 \r
207 case '-': Flags |= LEFT_JUSTIFY; break;\r
208 case '+': Flags |= PREFIX_SIGN; break;\r
209 case ' ': Flags |= PREFIX_BLANK; break;\r
210 case ',': Flags |= COMMA_TYPE; break;\r
211 case 'L':\r
212 case 'l': Flags |= LONG_TYPE; break;\r
213 \r
214 case '*':\r
215 Width = VA_ARG (Marker, UINTN);\r
216 break;\r
217 \r
218 case '0':\r
219 Flags |= PREFIX_ZERO;\r
220 case '1':\r
221 case '2':\r
222 case '3':\r
223 case '4':\r
224 case '5':\r
225 case '6':\r
226 case '7':\r
227 case '8':\r
228 case '9':\r
229 Count = 0;\r
230 do {\r
231 Count = (Count * 10) + *Format - '0';\r
232 Format++;\r
233 } while ((*Format >= '0') && (*Format <= '9'));\r
234 Format--;\r
235 Width = Count;\r
236 break;\r
237 \r
238 default:\r
239 Done = TRUE;\r
240 }\r
241 }\r
242\r
3eb9473e 243 switch (*Format) {\r
0f77dfb6 244 case 'p':\r
245 //\r
246 // Flag space, +, 0, L & l are invalid for type p.\r
247 //\r
248 Flags &= ~(PREFIX_BLANK| PREFIX_SIGN | LONG_TYPE);\r
249 if (sizeof (VOID *) > 4) {\r
250 Flags |= LONG_TYPE;\r
251 Value = VA_ARG (Marker, UINT64);\r
252 } else {\r
253 Value = VA_ARG (Marker, UINTN);\r
254 }\r
255 Flags |= PREFIX_ZERO;\r
256\r
257 EfiValueToHexStr (TempBuffer, Value, Flags, Width);\r
258 UnicodeStr = TempBuffer;\r
259\r
260 for ( ;(*UnicodeStr != '\0') && (Index < NumberOfCharacters - 1); UnicodeStr++) {\r
261 Buffer[Index++] = *UnicodeStr;\r
262 }\r
263 break;\r
264 \r
3eb9473e 265 case 'X':\r
266 Flags |= PREFIX_ZERO;\r
267 Width = sizeof (UINT64) * 2;\r
268 //\r
269 // break skiped on purpose\r
270 //\r
271 case 'x':\r
272 if ((Flags & LONG_TYPE) == LONG_TYPE) {\r
273 Value = VA_ARG (Marker, UINT64);\r
274 } else {\r
275 Value = VA_ARG (Marker, UINTN);\r
276 }\r
277\r
278 EfiValueToHexStr (TempBuffer, Value, Flags, Width);\r
279 UnicodeStr = TempBuffer;\r
280\r
281 for ( ;(*UnicodeStr != '\0') && (Index < NumberOfCharacters - 1); UnicodeStr++) {\r
282 Buffer[Index++] = *UnicodeStr;\r
283 }\r
284 break;\r
285\r
286 case 'd':\r
287 if ((Flags & LONG_TYPE) == LONG_TYPE) {\r
288 Value = VA_ARG (Marker, UINT64);\r
289 } else {\r
290 Value = (UINTN)VA_ARG (Marker, UINTN);\r
291 }\r
292\r
293 EfiValueToString (TempBuffer, Value, Flags, Width);\r
294 UnicodeStr = TempBuffer; \r
295\r
296 for ( ;(*UnicodeStr != '\0') && (Index < NumberOfCharacters - 1); UnicodeStr++) {\r
297 Buffer[Index++] = *UnicodeStr;\r
298 }\r
299 break;\r
300\r
301 case 's':\r
302 case 'S':\r
303 UnicodeStr = (CHAR16 *)VA_ARG (Marker, CHAR_W *);\r
304 if (UnicodeStr == NULL) {\r
305 UnicodeStr = L"<null string>";\r
306 }\r
307 for (Count = 0 ;(*UnicodeStr != '\0') && (Index < NumberOfCharacters - 1); UnicodeStr++, Count++) {\r
308 Buffer[Index++] = *UnicodeStr;\r
309 }\r
310 //\r
311 // Add padding if needed\r
312 //\r
313 for (; (Count < Width) && (Index < NumberOfCharacters - 1); Count++) {\r
314 Buffer[Index++] = ' ';\r
315 }\r
316\r
317 break;\r
318\r
319 case 'a':\r
320 AsciiStr = (CHAR8 *)VA_ARG (Marker, CHAR8 *);\r
321 if (AsciiStr == NULL) {\r
57d40fe2 322 AsciiStr = (CHAR8 *) "<null string>";\r
3eb9473e 323 }\r
324 for (Count = 0 ;(*AsciiStr != '\0') && (Index < NumberOfCharacters - 1); AsciiStr++, Count++) {\r
325 Buffer[Index++] = (CHAR_W)*AsciiStr;\r
326 }\r
327 //\r
328 // Add padding if needed\r
329 //\r
330 for (;(Count < Width) && (Index < NumberOfCharacters - 1); Count++) {\r
331 Buffer[Index++] = ' ';\r
332 }\r
333 break;\r
334\r
335 case 'c':\r
336 Buffer[Index++] = (CHAR_W)VA_ARG (Marker, UINTN);\r
337 break;\r
338\r
339 case 'g':\r
340 TmpGUID = VA_ARG (Marker, EFI_GUID *); \r
341 if (TmpGUID != NULL) {\r
342 Index += GuidToString (\r
343 TmpGUID, \r
344 &Buffer[Index], \r
345 BufferLeft\r
346 );\r
347 }\r
348 break;\r
349\r
350 case 't':\r
351 Index += TimeToString (\r
352 VA_ARG (Marker, EFI_TIME *), \r
353 &Buffer[Index], \r
354 BufferLeft\r
355 );\r
356 break;\r
357\r
358 case 'r':\r
359 Index += EfiStatusToString (\r
360 VA_ARG (Marker, EFI_STATUS), \r
361 &Buffer[Index], \r
362 BufferLeft\r
363 );\r
364 break;\r
365\r
366 case '%':\r
367 Buffer[Index++] = *Format;\r
368 break;\r
369 \r
370 default:\r
371 //\r
372 // if the type is unknown print it to the screen\r
373 //\r
374 Buffer[Index++] = *Format;\r
375 }\r
376 BufferLeft = BufferSize - Index * sizeof(CHAR_W) ;\r
377 } \r
378 }\r
379 Buffer[Index++] = '\0'; \r
380 \r
381 return &Buffer[Index] - StartOfBuffer;\r
382}\r
383\r
3eb9473e 384STATIC\r
385UINTN\r
386GuidToString (\r
387 IN EFI_GUID *Guid,\r
388 IN CHAR_W *Buffer,\r
389 IN UINTN BufferSize\r
390 )\r
391/*++\r
392\r
393Routine Description:\r
394\r
395 VSPrint worker function that prints an EFI_GUID.\r
396\r
397Arguments:\r
398\r
399 Guid - Pointer to GUID to print.\r
400\r
401 Buffer - Buffe to print Guid into.\r
402 \r
403 BufferSize - Size of Buffer.\r
404\r
405Returns: \r
406\r
407 Number of characters printed. \r
408\r
409--*/\r
410{\r
411 UINTN Size;\r
412\r
413 Size = SPrint (\r
414 Buffer,\r
415 BufferSize, \r
416 STRING_W ("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"),\r
417 (UINTN)Guid->Data1, \r
418 (UINTN)Guid->Data2,\r
419 (UINTN)Guid->Data3,\r
420 (UINTN)Guid->Data4[0],\r
421 (UINTN)Guid->Data4[1],\r
422 (UINTN)Guid->Data4[2],\r
423 (UINTN)Guid->Data4[3],\r
424 (UINTN)Guid->Data4[4],\r
425 (UINTN)Guid->Data4[5],\r
426 (UINTN)Guid->Data4[6],\r
427 (UINTN)Guid->Data4[7]\r
428 );\r
429\r
430 //\r
431 // SPrint will null terminate the string. The -1 skips the null\r
432 //\r
433 return Size - 1;\r
434}\r
435\r
436\r
437STATIC\r
438UINTN\r
439TimeToString (\r
440 IN EFI_TIME *Time,\r
441 OUT CHAR_W *Buffer,\r
442 IN UINTN BufferSize\r
443 )\r
444/*++\r
445\r
446Routine Description:\r
447\r
448 VSPrint worker function that prints EFI_TIME.\r
449\r
450Arguments:\r
451\r
452 Time - Pointer to EFI_TIME sturcture to print.\r
453\r
454 Buffer - Buffer to print Time into.\r
455 \r
456 BufferSize - Size of Buffer.\r
457\r
458Returns: \r
459\r
460 Number of characters printed. \r
461\r
462--*/\r
463{ \r
464 UINTN Size;\r
465\r
466 Size = SPrint (\r
467 Buffer,\r
468 BufferSize, \r
469 STRING_W ("%02d/%02d/%04d %02d:%02d"),\r
470 (UINTN)Time->Month,\r
471 (UINTN)Time->Day,\r
472 (UINTN)Time->Year,\r
473 (UINTN)Time->Hour,\r
474 (UINTN)Time->Minute\r
475 );\r
476\r
477 //\r
478 // SPrint will null terminate the string. The -1 skips the null\r
479 //\r
480 return Size - 1;\r
481} \r
482\r
483STATIC\r
484UINTN\r
485EfiStatusToString (\r
486 IN EFI_STATUS Status,\r
487 OUT CHAR_W *Buffer,\r
488 IN UINTN BufferSize\r
489 )\r
490/*++\r
491\r
492Routine Description:\r
493\r
494 VSPrint worker function that prints EFI_STATUS as a string. If string is\r
495 not known a hex value will be printed.\r
496\r
497Arguments:\r
498\r
499 Status - EFI_STATUS sturcture to print.\r
500\r
501 Buffer - Buffer to print EFI_STATUS message string into.\r
502 \r
503 BufferSize - Size of Buffer.\r
504\r
505Returns: \r
506\r
507 Number of characters printed. \r
508\r
509--*/\r
510{\r
511 UINTN Size;\r
512 CHAR8 *Desc;\r
513 \r
514 Desc = NULL;\r
515\r
516 //\r
517 // Can't use global Status String Array as UINTN is not constant for EBC\r
518 //\r
57d40fe2 519 if (Status == EFI_SUCCESS) { Desc = (CHAR8 *) "Success"; } else \r
520 if (Status == EFI_LOAD_ERROR) { Desc = (CHAR8 *) "Load Error"; } else\r
521 if (Status == EFI_INVALID_PARAMETER) { Desc = (CHAR8 *) "Invalid Parameter"; } else\r
522 if (Status == EFI_UNSUPPORTED) { Desc = (CHAR8 *) "Unsupported"; } else\r
523 if (Status == EFI_BAD_BUFFER_SIZE) { Desc = (CHAR8 *) "Bad Buffer Size"; } else\r
524 if (Status == EFI_BUFFER_TOO_SMALL) { Desc = (CHAR8 *) "Buffer Too Small"; } else\r
525 if (Status == EFI_NOT_READY) { Desc = (CHAR8 *) "Not Ready"; } else\r
526 if (Status == EFI_DEVICE_ERROR) { Desc = (CHAR8 *) "Device Error"; } else\r
527 if (Status == EFI_WRITE_PROTECTED) { Desc = (CHAR8 *) "Write Protected"; } else\r
528 if (Status == EFI_OUT_OF_RESOURCES) { Desc = (CHAR8 *) "Out of Resources"; } else\r
529 if (Status == EFI_VOLUME_CORRUPTED) { Desc = (CHAR8 *) "Volume Corrupt"; } else\r
530 if (Status == EFI_VOLUME_FULL) { Desc = (CHAR8 *) "Volume Full"; } else\r
531 if (Status == EFI_NO_MEDIA) { Desc = (CHAR8 *) "No Media"; } else\r
532 if (Status == EFI_MEDIA_CHANGED) { Desc = (CHAR8 *) "Media changed"; } else\r
533 if (Status == EFI_NOT_FOUND) { Desc = (CHAR8 *) "Not Found"; } else\r
534 if (Status == EFI_ACCESS_DENIED) { Desc = (CHAR8 *) "Access Denied"; } else\r
535 if (Status == EFI_NO_RESPONSE) { Desc = (CHAR8 *) "No Response"; } else\r
536 if (Status == EFI_NO_MAPPING) { Desc = (CHAR8 *) "No mapping"; } else\r
537 if (Status == EFI_TIMEOUT) { Desc = (CHAR8 *) "Time out"; } else\r
538 if (Status == EFI_NOT_STARTED) { Desc = (CHAR8 *) "Not started"; } else\r
539 if (Status == EFI_ALREADY_STARTED) { Desc = (CHAR8 *) "Already started"; } else\r
540 if (Status == EFI_ABORTED) { Desc = (CHAR8 *) "Aborted"; } else\r
541 if (Status == EFI_ICMP_ERROR) { Desc = (CHAR8 *) "ICMP Error"; } else\r
542 if (Status == EFI_TFTP_ERROR) { Desc = (CHAR8 *) "TFTP Error"; } else\r
543 if (Status == EFI_PROTOCOL_ERROR) { Desc = (CHAR8 *) "Protocol Error"; } else\r
544 if (Status == EFI_WARN_UNKNOWN_GLYPH) { Desc = (CHAR8 *) "Warning Unknown Glyph"; } else\r
545 if (Status == EFI_WARN_DELETE_FAILURE) { Desc = (CHAR8 *) "Warning Delete Failure"; } else\r
546 if (Status == EFI_WARN_WRITE_FAILURE) { Desc = (CHAR8 *) "Warning Write Failure"; } else\r
547 if (Status == EFI_WARN_BUFFER_TOO_SMALL) { Desc = (CHAR8 *) "Warning Buffer Too Small"; } \r
3eb9473e 548 \r
549 //\r
550 // If we found a match, copy the message to the user's buffer. Otherwise\r
551 // sprint the hex status code to their buffer.\r
552 //\r
553 if (Desc != NULL) {\r
554 Size = SPrint (Buffer, BufferSize, STRING_W ("%a"), Desc);\r
555 } else {\r
556 Size = SPrint (Buffer, BufferSize, STRING_W ("%X"), Status);\r
557 }\r
558 return Size - 1;\r
559}\r