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