1 /* $NetBSD: print.c,v 1.1.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