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