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