print.c revision 1.1 1 /* $NetBSD: print.c,v 1.1 2014/04/01 16:16:06 jakllsch Exp $ */
2
3 /*++
4
5 Copyright (c) 1998 Intel Corporation
6
7 Module Name:
8
9 print.c
10
11 Abstract:
12
13
14
15
16 Revision History
17
18 --*/
19
20 #include "lib.h"
21 #include "efistdarg.h" // !!!
22
23 //
24 // Declare runtime functions
25 //
26
27 #ifdef RUNTIME_CODE
28 #ifndef __GNUC__
29 #pragma RUNTIME_CODE(DbgPrint)
30
31 // For debugging..
32
33 /*
34 #pragma RUNTIME_CODE(_Print)
35 #pragma RUNTIME_CODE(PFLUSH)
36 #pragma RUNTIME_CODE(PSETATTR)
37 #pragma RUNTIME_CODE(PPUTC)
38 #pragma RUNTIME_CODE(PGETC)
39 #pragma RUNTIME_CODE(PITEM)
40 #pragma RUNTIME_CODE(ValueToHex)
41 #pragma RUNTIME_CODE(ValueToString)
42 #pragma RUNTIME_CODE(TimeToString)
43 */
44
45 #endif /* !defined(__GNUC__) */
46 #endif
47
48 //
49 //
50 //
51
52
53 #define PRINT_STRING_LEN 200
54 #define PRINT_ITEM_BUFFER_LEN 100
55
56 typedef struct {
57 BOOLEAN Ascii;
58 UINTN Index;
59 union {
60 CHAR16 *pw;
61 CHAR8 *pc;
62 } un;
63 } POINTER;
64
65 #define pw un.pw
66 #define pc un.pc
67
68 typedef struct _pitem {
69
70 POINTER Item;
71 CHAR16 Scratch[PRINT_ITEM_BUFFER_LEN];
72 UINTN Width;
73 UINTN FieldWidth;
74 UINTN *WidthParse;
75 CHAR16 Pad;
76 BOOLEAN PadBefore;
77 BOOLEAN Comma;
78 BOOLEAN Long;
79 } PRINT_ITEM;
80
81
82 typedef struct _pstate {
83 // Input
84 POINTER fmt;
85 va_list args;
86
87 // Output
88 CHAR16 *Buffer;
89 CHAR16 *End;
90 CHAR16 *Pos;
91 UINTN Len;
92
93 UINTN Attr;
94 UINTN RestoreAttr;
95
96 UINTN AttrNorm;
97 UINTN AttrHighlight;
98 UINTN AttrError;
99
100 INTN EFIAPI (*Output)(VOID *context, CHAR16 *str);
101 INTN EFIAPI (*SetAttr)(VOID *context, UINTN attr);
102 VOID *Context;
103
104 // Current item being formatted
105 struct _pitem *Item;
106 } PRINT_STATE;
107
108 //
109 // Internal fucntions
110 //
111
112 STATIC
113 UINTN
114 _Print (
115 IN PRINT_STATE *ps
116 );
117
118 STATIC
119 UINTN
120 _IPrint (
121 IN UINTN Column,
122 IN UINTN Row,
123 IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
124 IN CHAR16 *fmt,
125 IN CHAR8 *fmta,
126 IN va_list args
127 );
128
129 STATIC
130 INTN EFIAPI
131 _DbgOut (
132 IN VOID *Context,
133 IN CHAR16 *Buffer
134 );
135
136 STATIC
137 VOID
138 PFLUSH (
139 IN OUT PRINT_STATE *ps
140 );
141
142 STATIC
143 VOID
144 PPUTC (
145 IN OUT PRINT_STATE *ps,
146 IN CHAR16 c
147 );
148
149 STATIC
150 VOID
151 PITEM (
152 IN OUT PRINT_STATE *ps
153 );
154
155 STATIC
156 CHAR16
157 PGETC (
158 IN POINTER *p
159 );
160
161 STATIC
162 VOID
163 PSETATTR (
164 IN OUT PRINT_STATE *ps,
165 IN UINTN Attr
166 );
167
168 //
169 //
170 //
171
172 INTN EFIAPI
173 _SPrint (
174 IN VOID *Context,
175 IN CHAR16 *Buffer
176 );
177
178 INTN EFIAPI
179 _PoolPrint (
180 IN VOID *Context,
181 IN CHAR16 *Buffer
182 );
183
184 INTN
185 DbgPrint (
186 IN INTN mask,
187 IN CHAR8 *fmt,
188 ...
189 )
190 /*++
191
192 Routine Description:
193
194 Prints a formatted unicode string to the default StandardError console
195
196 Arguments:
197
198 mask - Bit mask of debug string. If a bit is set in the
199 mask that is also set in EFIDebug the string is
200 printed; otherwise, the string is not printed
201
202 fmt - Format string
203
204 Returns:
205
206 Length of string printed to the StandardError console
207
208 --*/
209 {
210 SIMPLE_TEXT_OUTPUT_INTERFACE *DbgOut;
211 PRINT_STATE ps;
212 va_list args;
213 UINTN back;
214 UINTN attr;
215 UINTN SavedAttribute;
216
217
218 if (!(EFIDebug & mask)) {
219 return 0;
220 }
221
222 va_start (args, fmt);
223 ZeroMem (&ps, sizeof(ps));
224
225 ps.Output = _DbgOut;
226 ps.fmt.Ascii = TRUE;
227 ps.fmt.pc = fmt;
228 va_copy(ps.args, args);
229 ps.Attr = EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_RED);
230
231 DbgOut = LibRuntimeDebugOut;
232
233 if (!DbgOut) {
234 DbgOut = ST->StdErr;
235 }
236
237 if (DbgOut) {
238 ps.Attr = DbgOut->Mode->Attribute;
239 ps.Context = DbgOut;
240 ps.SetAttr = (INTN EFIAPI (*)(VOID *, UINTN)) DbgOut->SetAttribute;
241 }
242
243 SavedAttribute = ps.Attr;
244
245 back = (ps.Attr >> 4) & 0xf;
246 ps.AttrNorm = EFI_TEXT_ATTR(EFI_LIGHTGRAY, back);
247 ps.AttrHighlight = EFI_TEXT_ATTR(EFI_WHITE, back);
248 ps.AttrError = EFI_TEXT_ATTR(EFI_YELLOW, back);
249
250 attr = ps.AttrNorm;
251
252 if (mask & D_WARN) {
253 attr = ps.AttrHighlight;
254 }
255
256 if (mask & D_ERROR) {
257 attr = ps.AttrError;
258 }
259
260 if (ps.SetAttr) {
261 ps.Attr = attr;
262 ps.SetAttr (ps.Context, attr);
263 }
264
265 _Print (&ps);
266
267 va_end (ps.args);
268 va_end (args);
269
270 //
271 // Restore original attributes
272 //
273
274 if (ps.SetAttr) {
275 ps.SetAttr (ps.Context, SavedAttribute);
276 }
277
278 return 0;
279 }
280
281 STATIC
282 INTN
283 IsLocalPrint(void *func)
284 {
285 if (func == _DbgOut || func == _SPrint || func == _PoolPrint)
286 return 1;
287 return 0;
288 }
289
290 STATIC
291 INTN EFIAPI
292 _DbgOut (
293 IN VOID *Context,
294 IN CHAR16 *Buffer
295 )
296 // Append string worker for DbgPrint
297 {
298 SIMPLE_TEXT_OUTPUT_INTERFACE *DbgOut;
299
300 DbgOut = Context;
301 // if (!DbgOut && ST && ST->ConOut) {
302 // DbgOut = ST->ConOut;
303 // }
304
305 if (DbgOut) {
306 if (IsLocalPrint(DbgOut->OutputString))
307 DbgOut->OutputString(DbgOut, Buffer);
308 else
309 uefi_call_wrapper(DbgOut->OutputString, 2, DbgOut, Buffer);
310 }
311
312 return 0;
313 }
314
315 INTN EFIAPI
316 _SPrint (
317 IN VOID *Context,
318 IN CHAR16 *Buffer
319 )
320 // Append string worker for SPrint, PoolPrint and CatPrint
321 {
322 UINTN len;
323 POOL_PRINT *spc;
324
325 spc = Context;
326 len = StrLen(Buffer);
327
328 //
329 // Is the string is over the max truncate it
330 //
331
332 if (spc->len + len > spc->maxlen) {
333 len = spc->maxlen - spc->len;
334 }
335
336 //
337 // Append the new text
338 //
339
340 CopyMem (spc->str + spc->len, Buffer, len * sizeof(CHAR16));
341 spc->len += len;
342
343 //
344 // Null terminate it
345 //
346
347 if (spc->len < spc->maxlen) {
348 spc->str[spc->len] = 0;
349 } else if (spc->maxlen) {
350 spc->str[spc->maxlen-1] = 0;
351 }
352
353 return 0;
354 }
355
356
357 INTN EFIAPI
358 _PoolPrint (
359 IN VOID *Context,
360 IN CHAR16 *Buffer
361 )
362 // Append string worker for PoolPrint and CatPrint
363 {
364 UINTN newlen;
365 POOL_PRINT *spc;
366
367 spc = Context;
368 newlen = spc->len + StrLen(Buffer) + 1;
369
370 //
371 // Is the string is over the max, grow the buffer
372 //
373
374 if (newlen > spc->maxlen) {
375
376 //
377 // Grow the pool buffer
378 //
379
380 newlen += PRINT_STRING_LEN;
381 spc->maxlen = newlen;
382 spc->str = ReallocatePool (
383 spc->str,
384 spc->len * sizeof(CHAR16),
385 spc->maxlen * sizeof(CHAR16)
386 );
387
388 if (!spc->str) {
389 spc->len = 0;
390 spc->maxlen = 0;
391 }
392 }
393
394 //
395 // Append the new text
396 //
397
398 return _SPrint (Context, Buffer);
399 }
400
401
402
403 VOID
404 _PoolCatPrint (
405 IN CHAR16 *fmt,
406 IN va_list args,
407 IN OUT POOL_PRINT *spc,
408 IN INTN EFIAPI (*Output)(VOID *context, CHAR16 *str)
409 )
410 // Dispath function for SPrint, PoolPrint, and CatPrint
411 {
412 PRINT_STATE ps;
413
414 ZeroMem (&ps, sizeof(ps));
415 ps.Output = Output;
416 ps.Context = spc;
417 ps.fmt.pw = fmt;
418 va_copy(ps.args, args);
419 _Print (&ps);
420 va_end(ps.args);
421 }
422
423
424
425 UINTN
426 SPrint (
427 OUT CHAR16 *Str,
428 IN UINTN StrSize,
429 IN CHAR16 *fmt,
430 ...
431 )
432 /*++
433
434 Routine Description:
435
436 Prints a formatted unicode string to a buffer
437
438 Arguments:
439
440 Str - Output buffer to print the formatted string into
441
442 StrSize - Size of Str. String is truncated to this size.
443 A size of 0 means there is no limit
444
445 fmt - The format string
446
447 Returns:
448
449 String length returned in buffer
450
451 --*/
452 {
453 POOL_PRINT spc;
454 va_list args;
455
456
457 va_start (args, fmt);
458 spc.str = Str;
459 spc.maxlen = StrSize / sizeof(CHAR16) - 1;
460 spc.len = 0;
461
462 _PoolCatPrint (fmt, args, &spc, _SPrint);
463 va_end (args);
464 return spc.len;
465 }
466
467
468 CHAR16 *
469 PoolPrint (
470 IN CHAR16 *fmt,
471 ...
472 )
473 /*++
474
475 Routine Description:
476
477 Prints a formatted unicode string to allocated pool. The caller
478 must free the resulting buffer.
479
480 Arguments:
481
482 fmt - The format string
483
484 Returns:
485
486 Allocated buffer with the formatted string printed in it.
487 The caller must free the allocated buffer. The buffer
488 allocation is not packed.
489
490 --*/
491 {
492 POOL_PRINT spc;
493 va_list args;
494
495 ZeroMem (&spc, sizeof(spc));
496 va_start (args, fmt);
497 _PoolCatPrint (fmt, args, &spc, _PoolPrint);
498 va_end (args);
499 return spc.str;
500 }
501
502
503
504 CHAR16 *
505 CatPrint (
506 IN OUT POOL_PRINT *Str,
507 IN CHAR16 *fmt,
508 ...
509 )
510 /*++
511
512 Routine Description:
513
514 Concatenates a formatted unicode string to allocated pool.
515 The caller must free the resulting buffer.
516
517 Arguments:
518
519 Str - Tracks the allocated pool, size in use, and
520 amount of pool allocated.
521
522 fmt - The format string
523
524 Returns:
525
526 Allocated buffer with the formatted string printed in it.
527 The caller must free the allocated buffer. The buffer
528 allocation is not packed.
529
530 --*/
531 {
532 va_list args;
533
534 va_start (args, fmt);
535 _PoolCatPrint (fmt, args, Str, _PoolPrint);
536 va_end (args);
537 return Str->str;
538 }
539
540
541
542 UINTN
543 Print (
544 IN CHAR16 *fmt,
545 ...
546 )
547 /*++
548
549 Routine Description:
550
551 Prints a formatted unicode string to the default console
552
553 Arguments:
554
555 fmt - Format string
556
557 Returns:
558
559 Length of string printed to the console
560
561 --*/
562 {
563 va_list args;
564 UINTN back;
565
566 va_start (args, fmt);
567 back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args);
568 va_end (args);
569 return back;
570 }
571
572 UINTN
573 VPrint (
574 IN CHAR16 *fmt,
575 va_list args
576 )
577 /*++
578
579 Routine Description:
580
581 Prints a formatted unicode string to the default console using a va_list
582
583 Arguments:
584
585 fmt - Format string
586 args - va_list
587 Returns:
588
589 Length of string printed to the console
590
591 --*/
592 {
593 return _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args);
594 }
595
596
597 UINTN
598 PrintAt (
599 IN UINTN Column,
600 IN UINTN Row,
601 IN CHAR16 *fmt,
602 ...
603 )
604 /*++
605
606 Routine Description:
607
608 Prints a formatted unicode string to the default console, at
609 the supplied cursor position
610
611 Arguments:
612
613 Column, Row - The cursor position to print the string at
614
615 fmt - Format string
616
617 Returns:
618
619 Length of string printed to the console
620
621 --*/
622 {
623 va_list args;
624 UINTN back;
625
626 va_start (args, fmt);
627 back = _IPrint (Column, Row, ST->ConOut, fmt, NULL, args);
628 va_end (args);
629 return back;
630 }
631
632
633 UINTN
634 IPrint (
635 IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
636 IN CHAR16 *fmt,
637 ...
638 )
639 /*++
640
641 Routine Description:
642
643 Prints a formatted unicode string to the specified console
644
645 Arguments:
646
647 Out - The console to print the string too
648
649 fmt - Format string
650
651 Returns:
652
653 Length of string printed to the console
654
655 --*/
656 {
657 va_list args;
658 UINTN back;
659
660 va_start (args, fmt);
661 back = _IPrint ((UINTN) -1, (UINTN) -1, Out, fmt, NULL, args);
662 va_end (args);
663 return back;
664 }
665
666
667 UINTN
668 IPrintAt (
669 IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
670 IN UINTN Column,
671 IN UINTN Row,
672 IN CHAR16 *fmt,
673 ...
674 )
675 /*++
676
677 Routine Description:
678
679 Prints a formatted unicode string to the specified console, at
680 the supplied cursor position
681
682 Arguments:
683
684 Out - The console to print the string too
685
686 Column, Row - The cursor position to print the string at
687
688 fmt - Format string
689
690 Returns:
691
692 Length of string printed to the console
693
694 --*/
695 {
696 va_list args;
697 UINTN back;
698
699 va_start (args, fmt);
700 back = _IPrint (Column, Row, ST->ConOut, fmt, NULL, args);
701 va_end (args);
702 return back;
703 }
704
705
706 UINTN
707 _IPrint (
708 IN UINTN Column,
709 IN UINTN Row,
710 IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
711 IN CHAR16 *fmt,
712 IN CHAR8 *fmta,
713 IN va_list args
714 )
715 // Display string worker for: Print, PrintAt, IPrint, IPrintAt
716 {
717 PRINT_STATE ps;
718 UINTN back;
719
720 ZeroMem (&ps, sizeof(ps));
721 ps.Context = Out;
722 ps.Output = (INTN EFIAPI (*)(VOID *, CHAR16 *)) Out->OutputString;
723 ps.SetAttr = (INTN EFIAPI (*)(VOID *, UINTN)) Out->SetAttribute;
724 ps.Attr = Out->Mode->Attribute;
725
726 back = (ps.Attr >> 4) & 0xF;
727 ps.AttrNorm = EFI_TEXT_ATTR(EFI_LIGHTGRAY, back);
728 ps.AttrHighlight = EFI_TEXT_ATTR(EFI_WHITE, back);
729 ps.AttrError = EFI_TEXT_ATTR(EFI_YELLOW, back);
730
731 if (fmt) {
732 ps.fmt.pw = fmt;
733 } else {
734 ps.fmt.Ascii = TRUE;
735 ps.fmt.pc = fmta;
736 }
737
738 va_copy(ps.args, args);
739
740 if (Column != (UINTN) -1) {
741 uefi_call_wrapper(Out->SetCursorPosition, 3, Out, Column, Row);
742 }
743
744 back = _Print (&ps);
745 va_end(ps.args);
746 return back;
747 }
748
749
750 UINTN
751 APrint (
752 IN CHAR8 *fmt,
753 ...
754 )
755 /*++
756
757 Routine Description:
758
759 For those whom really can't deal with unicode, a print
760 function that takes an ascii format string
761
762 Arguments:
763
764 fmt - ascii format string
765
766 Returns:
767
768 Length of string printed to the console
769
770 --*/
771
772 {
773 va_list args;
774 UINTN back;
775
776 va_start (args, fmt);
777 back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, NULL, fmt, args);
778 va_end (args);
779 return back;
780 }
781
782
783 STATIC
784 VOID
785 PFLUSH (
786 IN OUT PRINT_STATE *ps
787 )
788 {
789 *ps->Pos = 0;
790 if (IsLocalPrint(ps->Output))
791 ps->Output(ps->Context, ps->Buffer);
792 else
793 uefi_call_wrapper(ps->Output, 2, ps->Context, ps->Buffer);
794 ps->Pos = ps->Buffer;
795 }
796
797 STATIC
798 VOID
799 PSETATTR (
800 IN OUT PRINT_STATE *ps,
801 IN UINTN Attr
802 )
803 {
804 PFLUSH (ps);
805
806 ps->RestoreAttr = ps->Attr;
807 if (ps->SetAttr) {
808 uefi_call_wrapper(ps->SetAttr, 2, ps->Context, Attr);
809 }
810
811 ps->Attr = Attr;
812 }
813
814 STATIC
815 VOID
816 PPUTC (
817 IN OUT PRINT_STATE *ps,
818 IN CHAR16 c
819 )
820 {
821 // if this is a newline, add a carraige return
822 if (c == '\n') {
823 PPUTC (ps, '\r');
824 }
825
826 *ps->Pos = c;
827 ps->Pos += 1;
828 ps->Len += 1;
829
830 // if at the end of the buffer, flush it
831 if (ps->Pos >= ps->End) {
832 PFLUSH(ps);
833 }
834 }
835
836
837 STATIC
838 CHAR16
839 PGETC (
840 IN POINTER *p
841 )
842 {
843 CHAR16 c;
844
845 c = p->Ascii ? p->pc[p->Index] : p->pw[p->Index];
846 p->Index += 1;
847
848 return c;
849 }
850
851
852 STATIC
853 VOID
854 PITEM (
855 IN OUT PRINT_STATE *ps
856 )
857 {
858 UINTN Len, i;
859 PRINT_ITEM *Item;
860 CHAR16 c;
861
862 // Get the length of the item
863 Item = ps->Item;
864 Item->Item.Index = 0;
865 while (Item->Item.Index < Item->FieldWidth) {
866 c = PGETC(&Item->Item);
867 if (!c) {
868 Item->Item.Index -= 1;
869 break;
870 }
871 }
872 Len = Item->Item.Index;
873
874 // if there is no item field width, use the items width
875 if (Item->FieldWidth == (UINTN) -1) {
876 Item->FieldWidth = Len;
877 }
878
879 // if item is larger then width, update width
880 if (Len > Item->Width) {
881 Item->Width = Len;
882 }
883
884
885 // if pad field before, add pad char
886 if (Item->PadBefore) {
887 for (i=Item->Width; i < Item->FieldWidth; i+=1) {
888 PPUTC (ps, ' ');
889 }
890 }
891
892 // pad item
893 for (i=Len; i < Item->Width; i++) {
894 PPUTC (ps, Item->Pad);
895 }
896
897 // add the item
898 Item->Item.Index=0;
899 while (Item->Item.Index < Len) {
900 PPUTC (ps, PGETC(&Item->Item));
901 }
902
903 // If pad at the end, add pad char
904 if (!Item->PadBefore) {
905 for (i=Item->Width; i < Item->FieldWidth; i+=1) {
906 PPUTC (ps, ' ');
907 }
908 }
909 }
910
911
912 STATIC
913 UINTN
914 _Print (
915 IN PRINT_STATE *ps
916 )
917 /*++
918
919 Routine Description:
920
921 %w.lF - w = width
922 l = field width
923 F = format of arg
924
925 Args F:
926 0 - pad with zeros
927 - - justify on left (default is on right)
928 , - add comma's to field
929 * - width provided on stack
930 n - Set output attribute to normal (for this field only)
931 h - Set output attribute to highlight (for this field only)
932 e - Set output attribute to error (for this field only)
933 l - Value is 64 bits
934
935 a - ascii string
936 s - unicode string
937 X - fixed 8 byte value in hex
938 x - hex value
939 d - value as decimal
940 c - Unicode char
941 t - EFI time structure
942 g - Pointer to GUID
943 r - EFI status code (result code)
944
945 N - Set output attribute to normal
946 H - Set output attribute to highlight
947 E - Set output attribute to error
948 % - Print a %
949
950 Arguments:
951
952 SystemTable - The system table
953
954 Returns:
955
956 Number of charactors written
957
958 --*/
959 {
960 CHAR16 c;
961 UINTN Attr;
962 PRINT_ITEM Item;
963 CHAR16 Buffer[PRINT_STRING_LEN];
964
965 ps->Len = 0;
966 ps->Buffer = Buffer;
967 ps->Pos = Buffer;
968 ps->End = Buffer + PRINT_STRING_LEN - 1;
969 ps->Item = &Item;
970
971 ps->fmt.Index = 0;
972 while ((c = PGETC(&ps->fmt))) {
973
974 if (c != '%') {
975 PPUTC ( ps, c );
976 continue;
977 }
978
979 // setup for new item
980 Item.FieldWidth = (UINTN) -1;
981 Item.Width = 0;
982 Item.WidthParse = &Item.Width;
983 Item.Pad = ' ';
984 Item.PadBefore = TRUE;
985 Item.Comma = FALSE;
986 Item.Long = FALSE;
987 Item.Item.Ascii = FALSE;
988 Item.Item.pw = NULL;
989 ps->RestoreAttr = 0;
990 Attr = 0;
991
992 while ((c = PGETC(&ps->fmt))) {
993
994 switch (c) {
995
996 case '%':
997 //
998 // %% -> %
999 //
1000 Item.Item.pw = Item.Scratch;
1001 Item.Item.pw[0] = '%';
1002 Item.Item.pw[1] = 0;
1003 break;
1004
1005 case '0':
1006 Item.Pad = '0';
1007 break;
1008
1009 case '-':
1010 Item.PadBefore = FALSE;
1011 break;
1012
1013 case ',':
1014 Item.Comma = TRUE;
1015 break;
1016
1017 case '.':
1018 Item.WidthParse = &Item.FieldWidth;
1019 break;
1020
1021 case '*':
1022 *Item.WidthParse = va_arg(ps->args, UINTN);
1023 break;
1024
1025 case '1':
1026 case '2':
1027 case '3':
1028 case '4':
1029 case '5':
1030 case '6':
1031 case '7':
1032 case '8':
1033 case '9':
1034 *Item.WidthParse = 0;
1035 do {
1036 *Item.WidthParse = *Item.WidthParse * 10 + c - '0';
1037 c = PGETC(&ps->fmt);
1038 } while (c >= '0' && c <= '9') ;
1039 ps->fmt.Index -= 1;
1040 break;
1041
1042 case 'a':
1043 Item.Item.pc = va_arg(ps->args, CHAR8 *);
1044 Item.Item.Ascii = TRUE;
1045 if (!Item.Item.pc) {
1046 Item.Item.pc = (CHAR8 *)"(null)";
1047 }
1048 break;
1049
1050 case 's':
1051 Item.Item.pw = va_arg(ps->args, CHAR16 *);
1052 if (!Item.Item.pw) {
1053 Item.Item.pw = L"(null)";
1054 }
1055 break;
1056
1057 case 'c':
1058 Item.Item.pw = Item.Scratch;
1059 Item.Item.pw[0] = (CHAR16) va_arg(ps->args, UINTN);
1060 Item.Item.pw[1] = 0;
1061 break;
1062
1063 case 'l':
1064 Item.Long = TRUE;
1065 break;
1066
1067 case 'X':
1068 Item.Width = Item.Long ? 16 : 8;
1069 Item.Pad = '0';
1070 case 'x':
1071 Item.Item.pw = Item.Scratch;
1072 ValueToHex (
1073 Item.Item.pw,
1074 Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
1075 );
1076
1077 break;
1078
1079
1080 case 'g':
1081 Item.Item.pw = Item.Scratch;
1082 GuidToString (Item.Item.pw, va_arg(ps->args, EFI_GUID *));
1083 break;
1084
1085 case 'd':
1086 Item.Item.pw = Item.Scratch;
1087 ValueToString (
1088 Item.Item.pw,
1089 Item.Comma,
1090 Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
1091 );
1092 break
1093 ;
1094 case 't':
1095 Item.Item.pw = Item.Scratch;
1096 TimeToString (Item.Item.pw, va_arg(ps->args, EFI_TIME *));
1097 break;
1098
1099 case 'r':
1100 Item.Item.pw = Item.Scratch;
1101 StatusToString (Item.Item.pw, va_arg(ps->args, EFI_STATUS));
1102 break;
1103
1104 case 'n':
1105 PSETATTR(ps, ps->AttrNorm);
1106 break;
1107
1108 case 'h':
1109 PSETATTR(ps, ps->AttrHighlight);
1110 break;
1111
1112 case 'e':
1113 PSETATTR(ps, ps->AttrError);
1114 break;
1115
1116 case 'N':
1117 Attr = ps->AttrNorm;
1118 break;
1119
1120 case 'H':
1121 Attr = ps->AttrHighlight;
1122 break;
1123
1124 case 'E':
1125 Attr = ps->AttrError;
1126 break;
1127
1128 default:
1129 Item.Item.pw = Item.Scratch;
1130 Item.Item.pw[0] = '?';
1131 Item.Item.pw[1] = 0;
1132 break;
1133 }
1134
1135 // if we have an Item
1136 if (Item.Item.pw) {
1137 PITEM (ps);
1138 break;
1139 }
1140
1141 // if we have an Attr set
1142 if (Attr) {
1143 PSETATTR(ps, Attr);
1144 ps->RestoreAttr = 0;
1145 break;
1146 }
1147 }
1148
1149 if (ps->RestoreAttr) {
1150 PSETATTR(ps, ps->RestoreAttr);
1151 }
1152 }
1153
1154 // Flush buffer
1155 PFLUSH (ps);
1156 return ps->Len;
1157 }
1158
1159 STATIC CHAR8 Hex[] = {'0','1','2','3','4','5','6','7',
1160 '8','9','A','B','C','D','E','F'};
1161
1162 VOID
1163 ValueToHex (
1164 IN CHAR16 *Buffer,
1165 IN UINT64 v
1166 )
1167 {
1168 CHAR8 str[30], *p1;
1169 CHAR16 *p2;
1170
1171 if (!v) {
1172 Buffer[0] = '0';
1173 Buffer[1] = 0;
1174 return ;
1175 }
1176
1177 p1 = str;
1178 p2 = Buffer;
1179
1180 while (v) {
1181 *(p1++) = Hex[v & 0xf];
1182 v = RShiftU64 (v, 4);
1183 }
1184
1185 while (p1 != str) {
1186 *(p2++) = *(--p1);
1187 }
1188 *p2 = 0;
1189 }
1190
1191
1192 VOID
1193 ValueToString (
1194 IN CHAR16 *Buffer,
1195 IN BOOLEAN Comma,
1196 IN INT64 v
1197 )
1198 {
1199 STATIC CHAR8 ca[] = { 3, 1, 2 };
1200 CHAR8 str[40], *p1;
1201 CHAR16 *p2;
1202 UINTN c, r;
1203
1204 if (!v) {
1205 Buffer[0] = '0';
1206 Buffer[1] = 0;
1207 return ;
1208 }
1209
1210 p1 = str;
1211 p2 = Buffer;
1212
1213 if (v < 0) {
1214 *(p2++) = '-';
1215 v = -v;
1216 }
1217
1218 while (v) {
1219 v = (INT64)DivU64x32 ((UINT64)v, 10, &r);
1220 *(p1++) = (CHAR8)r + '0';
1221 }
1222
1223 c = (Comma ? ca[(p1 - str) % 3] : 999) + 1;
1224 while (p1 != str) {
1225
1226 c -= 1;
1227 if (!c) {
1228 *(p2++) = ',';
1229 c = 3;
1230 }
1231
1232 *(p2++) = *(--p1);
1233 }
1234 *p2 = 0;
1235 }
1236
1237 VOID
1238 TimeToString (
1239 OUT CHAR16 *Buffer,
1240 IN EFI_TIME *Time
1241 )
1242 {
1243 UINTN Hour, Year;
1244 CHAR16 AmPm;
1245
1246 AmPm = 'a';
1247 Hour = Time->Hour;
1248 if (Time->Hour == 0) {
1249 Hour = 12;
1250 } else if (Time->Hour >= 12) {
1251 AmPm = 'p';
1252 if (Time->Hour >= 13) {
1253 Hour -= 12;
1254 }
1255 }
1256
1257 Year = Time->Year % 100;
1258
1259 // bugbug: for now just print it any old way
1260 SPrint (Buffer, 0, L"%02d/%02d/%02d %02d:%02d%c",
1261 Time->Month,
1262 Time->Day,
1263 Year,
1264 Hour,
1265 Time->Minute,
1266 AmPm
1267 );
1268 }
1269
1270
1271
1272
1273 VOID
1274 DumpHex (
1275 IN UINTN Indent,
1276 IN UINTN Offset,
1277 IN UINTN DataSize,
1278 IN VOID *UserData
1279 )
1280 {
1281 CHAR8 *Data, Val[50], Str[20], c;
1282 UINTN Size, Index;
1283
1284 UINTN ScreenCount;
1285 UINTN TempColumn;
1286 UINTN ScreenSize;
1287 CHAR16 ReturnStr[1];
1288
1289
1290 uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &TempColumn, &ScreenSize);
1291 ScreenCount = 0;
1292 ScreenSize -= 2;
1293
1294 Data = UserData;
1295 while (DataSize) {
1296 Size = 16;
1297 if (Size > DataSize) {
1298 Size = DataSize;
1299 }
1300
1301 for (Index=0; Index < Size; Index += 1) {
1302 c = Data[Index];
1303 Val[Index*3+0] = Hex[c>>4];
1304 Val[Index*3+1] = Hex[c&0xF];
1305 Val[Index*3+2] = (Index == 7)?'-':' ';
1306 Str[Index] = (c < ' ' || c > 'z') ? '.' : c;
1307 }
1308
1309 Val[Index*3] = 0;
1310 Str[Index] = 0;
1311 Print (L"%*a%X: %-.48a *%a*\n", Indent, "", Offset, Val, Str);
1312
1313 Data += Size;
1314 Offset += Size;
1315 DataSize -= Size;
1316
1317 ScreenCount++;
1318 if (ScreenCount >= ScreenSize && ScreenSize != 0) {
1319 //
1320 // If ScreenSize == 0 we have the console redirected so don't
1321 // block updates
1322 //
1323 ScreenCount = 0;
1324 Print (L"Press Enter to continue :");
1325 Input (L"", ReturnStr, sizeof(ReturnStr)/sizeof(CHAR16));
1326 Print (L"\n");
1327 }
1328
1329 }
1330 }
1331