]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/TianoTools/Common/PeiLib/Print/Print.c
13e7d33ae04b1a68604953bf4bce75bc918e34f4
[mirror_edk2.git] / Tools / Source / TianoTools / Common / PeiLib / Print / Print.c
1 /*++
2
3 Copyright (c) 2004, Intel Corporation
4 All rights reserved. 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 AvSPrint(). AvSPrint() enables very
19 simple implemenation of debug prints.
20
21 You can not Print more than PEI_LIB_MAX_PRINT_BUFFER characters at a
22 time. This makes the implementation very simple.
23
24 AvSPrint 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 'X' - argument is a UINTN hex number, prefix '0'
43 'x' - argument is a hex number
44 'd' - argument is a decimal number
45 'a' - argument is an ascii string
46 'S', 's' - argument is an Unicode string
47 'g' - argument is a pointer to an EFI_GUID
48 't' - argument is a pointer to an EFI_TIME structure
49 'c' - argument is an ascii character
50 'r' - argument is EFI_STATUS
51 '%' - Print a %
52
53 --*/
54
55 #include "Tiano.h"
56 #include "Pei.h"
57 #include "PeiLib.h"
58 #include "Print.h"
59
60
61 STATIC
62 CHAR8 *
63 GetFlagsAndWidth (
64 IN CHAR8 *Format,
65 OUT UINTN *Flags,
66 OUT UINTN *Width,
67 IN OUT VA_LIST *Marker
68 );
69
70 STATIC
71 UINTN
72 ValueToString (
73 IN OUT CHAR8 *Buffer,
74 IN INT64 Value,
75 IN UINTN Flags,
76 IN UINTN Width
77 );
78
79 STATIC
80 UINTN
81 ValueTomHexStr (
82 IN OUT CHAR8 *Buffer,
83 IN UINT64 Value,
84 IN UINTN Flags,
85 IN UINTN Width
86 );
87
88 STATIC
89 UINTN
90 GuidToString (
91 IN EFI_GUID *Guid,
92 IN OUT CHAR8 *Buffer,
93 IN UINTN BufferSize
94 );
95
96 STATIC
97 UINTN
98 TimeToString (
99 IN EFI_TIME *Time,
100 IN OUT CHAR8 *Buffer,
101 IN UINTN BufferSize
102 );
103
104 STATIC
105 UINTN
106 EfiStatusToString (
107 IN EFI_STATUS Status,
108 OUT CHAR8 *Buffer,
109 IN UINTN BufferSize
110 );
111
112
113 UINTN
114 ASPrint (
115 OUT CHAR8 *Buffer,
116 IN UINTN BufferSize,
117 IN CONST CHAR8 *Format,
118 ...
119 )
120 /*++
121
122 Routine Description:
123
124 ASPrint function to process format and place the results in Buffer.
125
126 Arguments:
127
128 Buffer - Ascii buffer to print the results of the parsing of Format into.
129
130 BufferSize - Maximum number of characters to put into buffer. Zero means no
131 limit.
132
133 Format - Ascii format string see file header for more details.
134
135 ... - Vararg list consumed by processing Format.
136
137 Returns:
138
139 Number of characters printed.
140
141 --*/
142 {
143 UINTN Return;
144 VA_LIST Marker;
145
146 VA_START(Marker, Format);
147 Return = AvSPrint(Buffer, BufferSize, Format, Marker);
148 VA_END (Marker);
149
150 return Return;
151 }
152
153
154 UINTN
155 AvSPrint (
156 OUT CHAR8 *StartOfBuffer,
157 IN UINTN BufferSize,
158 IN CONST CHAR8 *FormatString,
159 IN VA_LIST Marker
160 )
161 /*++
162
163 Routine Description:
164
165 AvSPrint function to process format and place the results in Buffer. Since a
166 VA_LIST is used this rountine allows the nesting of Vararg routines. Thus
167 this is the main print working routine
168
169 Arguments:
170
171 StartOfBuffer - Ascii buffer to print the results of the parsing of Format into.
172
173 BufferSize - Maximum number of characters to put into buffer. Zero means
174 no limit.
175
176 FormatString - Ascii format string see file header for more details.
177
178 Marker - Vararg list consumed by processing Format.
179
180 Returns:
181
182 Number of characters printed.
183
184 --*/
185 {
186 CHAR8 *Buffer;
187 CHAR8 *AsciiStr;
188 CHAR16 *UnicodeStr;
189 CHAR8 *Format;
190 UINTN Index;
191 UINTN Flags;
192 UINTN Width;
193 UINT64 Value;
194
195 //
196 // Process the format string. Stop if Buffer is over run.
197 //
198
199 Buffer = StartOfBuffer;
200 Format = (CHAR8 *)FormatString;
201 for (Index = 0; (*Format != '\0') && (Index < BufferSize); Format++) {
202 if (*Format != '%') {
203 if (*Format == '\n') {
204 //
205 // If carage return add line feed
206 //
207 Buffer[Index++] = '\r';
208 }
209 Buffer[Index++] = *Format;
210 } else {
211
212 //
213 // Now it's time to parse what follows after %
214 //
215 Format = GetFlagsAndWidth (Format, &Flags, &Width, &Marker);
216 switch (*Format) {
217 case 'X':
218 Flags |= PREFIX_ZERO;
219 Width = sizeof (UINT64) * 2;
220 //
221 // break skiped on purpose
222 //
223 case 'x':
224 if ((Flags & LONG_TYPE) == LONG_TYPE) {
225 Value = VA_ARG (Marker, UINT64);
226 } else {
227 Value = VA_ARG (Marker, UINTN);
228 }
229 Index += ValueTomHexStr (&Buffer[Index], Value, Flags, Width);
230 break;
231
232 case 'd':
233 if ((Flags & LONG_TYPE) == LONG_TYPE) {
234 Value = VA_ARG (Marker, UINT64);
235 } else {
236 Value = (UINTN)VA_ARG (Marker, UINTN);
237 }
238 Index += ValueToString (&Buffer[Index], Value, Flags, Width);
239 break;
240
241 case 's':
242 case 'S':
243 UnicodeStr = (CHAR16 *)VA_ARG (Marker, CHAR16 *);
244 if (UnicodeStr == NULL) {
245 UnicodeStr = L"<null string>";
246 }
247 for ( ;*UnicodeStr != '\0'; UnicodeStr++) {
248 Buffer[Index++] = (CHAR8)*UnicodeStr;
249 }
250 break;
251
252 case 'a':
253 AsciiStr = (CHAR8 *)VA_ARG (Marker, CHAR8 *);
254 if (AsciiStr == NULL) {
255 AsciiStr = "<null string>";
256 }
257 while (*AsciiStr != '\0') {
258 Buffer[Index++] = *AsciiStr++;
259 }
260 break;
261
262 case 'c':
263 Buffer[Index++] = (CHAR8)VA_ARG (Marker, UINTN);
264 break;
265
266 case 'g':
267 Index += GuidToString (
268 VA_ARG (Marker, EFI_GUID *),
269 &Buffer[Index],
270 BufferSize
271 );
272 break;
273
274 case 't':
275 Index += TimeToString (
276 VA_ARG (Marker, EFI_TIME *),
277 &Buffer[Index],
278 BufferSize
279 );
280 break;
281
282 case 'r':
283 Index += EfiStatusToString (
284 VA_ARG (Marker, EFI_STATUS),
285 &Buffer[Index],
286 BufferSize
287 );
288 break;
289
290 case '%':
291 Buffer[Index++] = *Format;
292 break;
293
294 default:
295 //
296 // if the type is unknown print it to the screen
297 //
298 Buffer[Index++] = *Format;
299 }
300
301 }
302 }
303 Buffer[Index++] = '\0';
304
305 return &Buffer[Index] - StartOfBuffer;
306 }
307
308
309
310 STATIC
311 CHAR8 *
312 GetFlagsAndWidth (
313 IN CHAR8 *Format,
314 OUT UINTN *Flags,
315 OUT UINTN *Width,
316 IN OUT VA_LIST *Marker
317 )
318 /*++
319
320 Routine Description:
321
322 AvSPrint worker function that parses flag and width information from the
323 Format string and returns the next index into the Format string that needs
324 to be parsed. See file headed for details of Flag and Width.
325
326 Arguments:
327
328 Format - Current location in the AvSPrint format string.
329
330 Flags - Returns flags
331
332 Width - Returns width of element
333
334 Marker - Vararg list that may be paritally consumed and returned.
335
336 Returns:
337
338 Pointer indexed into the Format string for all the information parsed
339 by this routine.
340
341 --*/
342 {
343 UINTN Count;
344 BOOLEAN Done;
345
346 *Flags = 0;
347 *Width = 0;
348 for (Done = FALSE; !Done; ) {
349 Format++;
350
351 switch (*Format) {
352
353 case '-': *Flags |= LEFT_JUSTIFY; break;
354 case '+': *Flags |= PREFIX_SIGN; break;
355 case ' ': *Flags |= PREFIX_BLANK; break;
356 case ',': *Flags |= COMMA_TYPE; break;
357 case 'L':
358 case 'l': *Flags |= LONG_TYPE; break;
359
360 case '*':
361 *Width = VA_ARG (*Marker, UINTN);
362 break;
363
364 case '0':
365 *Flags |= PREFIX_ZERO;
366 case '1':
367 case '2':
368 case '3':
369 case '4':
370 case '5':
371 case '6':
372 case '7':
373 case '8':
374 case '9':
375 Count = 0;
376 do {
377 Count = (Count * 10) + *Format - '0';
378 Format++;
379 } while ((*Format >= '0') && (*Format <= '9'));
380 Format--;
381 *Width = Count;
382 break;
383
384 default:
385 Done = TRUE;
386 }
387 }
388 return Format;
389 }
390
391 static CHAR8 mHexStr[] = { '0','1','2','3','4','5','6','7',
392 '8','9','A','B','C','D','E','F' };
393
394 STATIC
395 UINTN
396 ValueTomHexStr (
397 IN OUT CHAR8 *Buffer,
398 IN UINT64 Value,
399 IN UINTN Flags,
400 IN UINTN Width
401 )
402 /*++
403
404 Routine Description:
405
406 AvSPrint worker function that prints a Value as a hex number in Buffer
407
408 Arguments:
409
410 Buffer - Location to place ascii hex string of Value.
411
412 Value - Hex value to convert to a string in Buffer.
413
414 Flags - Flags to use in printing Hex string, see file header for details.
415
416 Width - Width of hex value.
417
418 Returns:
419
420 Number of characters printed.
421
422 --*/
423 {
424 CHAR8 TempBuffer[30];
425 CHAR8 *TempStr;
426 CHAR8 Prefix;
427 CHAR8 *BufferPtr;
428 UINTN Count;
429 UINTN Index;
430
431 TempStr = TempBuffer;
432 BufferPtr = Buffer;
433
434 //
435 // Count starts at one since we will null terminate. Each iteration of the
436 // loop picks off one nibble. Oh yea TempStr ends up backwards
437 //
438 Count = 0;
439 do {
440 *(TempStr++) = mHexStr[Value & 0x0f];
441 Value = RShiftU64 (Value, 4);
442 Count++;
443 } while (Value != 0);
444
445 if (Flags & PREFIX_ZERO) {
446 Prefix = '0';
447 } else if (!(Flags & LEFT_JUSTIFY)) {
448 Prefix = ' ';
449 } else {
450 Prefix = 0x00;
451 }
452 for (Index = Count; Index < Width; Index++) {
453 *(TempStr++) = Prefix;
454 }
455
456 //
457 // Reverse temp string into Buffer.
458 //
459 while (TempStr != TempBuffer) {
460 *(BufferPtr++) = *(--TempStr);
461 }
462
463 *BufferPtr = 0;
464 return Index;
465 }
466
467 STATIC
468 UINTN
469 ValueToString (
470 IN OUT CHAR8 *Buffer,
471 IN INT64 Value,
472 IN UINTN Flags,
473 IN UINTN Width
474 )
475 /*++
476
477 Routine Description:
478
479 AvSPrint worker function that prints a Value as a decimal number in Buffer
480
481 Arguments:
482
483 Buffer - Location to place ascii decimal number string of Value.
484
485 Value - Decimal value to convert to a string in Buffer.
486
487 Flags - Flags to use in printing decimal string, see file header for details.
488
489 Width - Width of hex value.
490
491 Returns:
492
493 Number of characters printed.
494
495 --*/
496 {
497 CHAR8 TempBuffer[30];
498 CHAR8 *TempStr;
499 CHAR8 *BufferPtr;
500 UINTN Count;
501 UINTN Remainder;
502
503 TempStr = TempBuffer;
504 BufferPtr = Buffer;
505 Count = 0;
506
507 if (Value < 0) {
508 *(BufferPtr++) = '-';
509 Value = -Value;
510 Count++;
511 }
512
513 do {
514 Value = (INT64)DivU64x32 ((UINT64)Value, 10, &Remainder);
515 *(TempStr++) = (CHAR8)(Remainder + '0');
516 Count++;
517 if ((Flags & COMMA_TYPE) == COMMA_TYPE) {
518 if (Count % 3 == 0) {
519 *(TempStr++) = ',';
520 }
521 }
522 } while (Value != 0);
523
524 //
525 // Reverse temp string into Buffer.
526 //
527 while (TempStr != TempBuffer) {
528 *(BufferPtr++) = *(--TempStr);
529 }
530
531 *BufferPtr = 0;
532 return Count;
533 }
534
535 STATIC
536 UINTN
537 GuidToString (
538 IN EFI_GUID *Guid,
539 IN CHAR8 *Buffer,
540 IN UINTN BufferSize
541 )
542 /*++
543
544 Routine Description:
545
546 AvSPrint worker function that prints an EFI_GUID.
547
548 Arguments:
549
550 Guid - Pointer to GUID to print.
551
552 Buffer - Buffe to print Guid into.
553
554 BufferSize - Size of Buffer.
555
556 Returns:
557
558 Number of characters printed.
559
560 --*/
561 {
562 UINTN Size;
563
564 Size = ASPrint (
565 Buffer,
566 BufferSize,
567 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
568 Guid->Data1,
569 Guid->Data2,
570 Guid->Data3,
571 Guid->Data4[0],
572 Guid->Data4[1],
573 Guid->Data4[2],
574 Guid->Data4[3],
575 Guid->Data4[4],
576 Guid->Data4[5],
577 Guid->Data4[6],
578 Guid->Data4[7]
579 );
580
581 //
582 // ASPrint will null terminate the string. The -1 skips the null
583 //
584 return Size - 1;
585 }
586
587
588 STATIC
589 UINTN
590 TimeToString (
591 IN EFI_TIME *Time,
592 OUT CHAR8 *Buffer,
593 IN UINTN BufferSize
594 )
595 /*++
596
597 Routine Description:
598
599 AvSPrint worker function that prints EFI_TIME.
600
601 Arguments:
602
603 Time - Pointer to EFI_TIME sturcture to print.
604
605 Buffer - Buffer to print Time into.
606
607 BufferSize - Size of Buffer.
608
609 Returns:
610
611 Number of characters printed.
612
613 --*/
614 {
615 UINTN Size;
616
617 Size = ASPrint (
618 Buffer,
619 BufferSize,
620 "%02d/%02d/%04d %02d:%02d",
621 Time->Month,
622 Time->Day,
623 Time->Year,
624 Time->Hour,
625 Time->Minute
626 );
627
628 //
629 // ASPrint will null terminate the string. The -1 skips the null
630 //
631 return Size - 1;
632 }
633
634 STATIC
635 UINTN
636 EfiStatusToString (
637 IN EFI_STATUS Status,
638 OUT CHAR8 *Buffer,
639 IN UINTN BufferSize
640 )
641 /*++
642
643 Routine Description:
644
645 AvSPrint worker function that prints EFI_STATUS as a string. If string is
646 not known a hex value will be printed.
647
648 Arguments:
649
650 Status - EFI_STATUS sturcture to print.
651
652 Buffer - Buffer to print EFI_STATUS message string into.
653
654 BufferSize - Size of Buffer.
655
656 Returns:
657
658 Number of characters printed.
659
660 --*/
661 {
662 UINTN Size;
663 CHAR8 *Desc;
664
665 if (Status == EFI_SUCCESS) {
666 Desc = "Success";
667 } else if (Status == EFI_LOAD_ERROR) {
668 Desc = "Load Error";
669 } else if (Status == EFI_INVALID_PARAMETER) {
670 Desc = "Invalid Parameter";
671 } else if (Status == EFI_UNSUPPORTED) {
672 Desc = "Unsupported";
673 } else if (Status == EFI_BAD_BUFFER_SIZE) {
674 Desc = "Bad Buffer Size";
675 } else if (Status == EFI_BUFFER_TOO_SMALL) {
676 Desc = "Buffer Too Small";
677 } else if (Status == EFI_NOT_READY) {
678 Desc = "Not Ready";
679 } else if (Status == EFI_DEVICE_ERROR) {
680 Desc = "Device Error";
681 } else if (Status == EFI_WRITE_PROTECTED) {
682 Desc = "Write Protected";
683 } else if (Status == EFI_OUT_OF_RESOURCES) {
684 Desc = "Out of Resources";
685 } else if (Status == EFI_VOLUME_CORRUPTED) {
686 Desc = "Volume Corrupt";
687 } else if (Status == EFI_VOLUME_FULL) {
688 Desc = "Volume Full";
689 } else if (Status == EFI_NO_MEDIA) {
690 Desc = "No Media";
691 } else if (Status == EFI_MEDIA_CHANGED) {
692 Desc = "Media changed";
693 } else if (Status == EFI_NOT_FOUND) {
694 Desc = "Not Found";
695 } else if (Status == EFI_ACCESS_DENIED) {
696 Desc = "Access Denied";
697 } else if (Status == EFI_NO_RESPONSE) {
698 Desc = "No Response";
699 } else if (Status == EFI_NO_MAPPING) {
700 Desc = "No mapping";
701 } else if (Status == EFI_TIMEOUT) {
702 Desc = "Time out";
703 } else if (Status == EFI_NOT_STARTED) {
704 Desc = "Not started";
705 } else if (Status == EFI_ALREADY_STARTED) {
706 Desc = "Already started";
707 } else if (Status == EFI_ABORTED) {
708 Desc = "Aborted";
709 } else if (Status == EFI_ICMP_ERROR) {
710 Desc = "ICMP Error";
711 } else if (Status == EFI_TFTP_ERROR) {
712 Desc = "TFTP Error";
713 } else if (Status == EFI_PROTOCOL_ERROR) {
714 Desc = "Protocol Error";
715 } else if (Status == EFI_WARN_UNKNOWN_GLYPH) {
716 Desc = "Warning Unknown Glyph";
717 } else if (Status == EFI_WARN_DELETE_FAILURE) {
718 Desc = "Warning Delete Failure";
719 } else if (Status == EFI_WARN_WRITE_FAILURE) {
720 Desc = "Warning Write Failure";
721 } else if (Status == EFI_WARN_BUFFER_TOO_SMALL) {
722 Desc = "Warning Buffer Too Small";
723 } else {
724 Desc = NULL;
725 }
726 //
727 // If we found a match, copy the message to the user's buffer. Otherwise
728 // sprint the hex status code to their buffer.
729 //
730 if (Desc != NULL) {
731 Size = ASPrint (Buffer, BufferSize, "%a", Desc);
732 } else {
733 Size = ASPrint (Buffer, BufferSize, "%X", Status);
734 }
735 return Size - 1;
736 }