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