1 /** 2 @file 3 Display the system table 4 5 Copyright (c) 2011-2012, Intel Corporation 6 All rights reserved. This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 #include <WebServer.h> 17 18 19 /** 20 Display the EFI Table Header 21 22 @param [in] SocketFD The socket's file descriptor to add to the list. 23 @param [in] pPort The WSDT_PORT structure address 24 @param [in] pHeader Address of the EFI_TABLE_HEADER structure 25 26 @retval EFI_SUCCESS The request was successfully processed 27 28 **/ 29 EFI_STATUS 30 EfiTableHeader ( 31 IN int SocketFD, 32 IN WSDT_PORT * pPort, 33 IN EFI_TABLE_HEADER * pHeader 34 ) 35 { 36 EFI_STATUS Status; 37 38 DBG_ENTER ( ); 39 40 // 41 // Send the handles page 42 // 43 for ( ; ; ) { 44 /// 45 /// A 64-bit signature that identifies the type of table that follows. 46 /// Unique signatures have been generated for the EFI System Table, 47 /// the EFI Boot Services Table, and the EFI Runtime Services Table. 48 /// 49 Status = RowHexValue ( SocketFD, 50 pPort, 51 "Hdr.Signature", 52 pHeader->Signature, 53 NULL ); 54 if ( EFI_ERROR ( Status )) { 55 break; 56 } 57 58 /// 59 /// The revision of the EFI Specification to which this table 60 /// conforms. The upper 16 bits of this field contain the major 61 /// revision value, and the lower 16 bits contain the minor revision 62 /// value. The minor revision values are limited to the range of 00..99. 63 /// 64 Status = RowRevision ( SocketFD, 65 pPort, 66 "Hdr.Revision", 67 pHeader->Revision ); 68 if ( EFI_ERROR ( Status )) { 69 break; 70 } 71 72 /// 73 /// The size, in bytes, of the entire table including the EFI_TABLE_HEADER. 74 /// 75 Status = RowDecimalValue ( SocketFD, 76 pPort, 77 "Hdr.HeaderSize", 78 pHeader->HeaderSize ); 79 if ( EFI_ERROR ( Status )) { 80 break; 81 } 82 83 /// 84 /// The 32-bit CRC for the entire table. This value is computed by 85 /// setting this field to 0, and computing the 32-bit CRC for HeaderSize bytes. 86 /// 87 Status = RowHexValue ( SocketFD, 88 pPort, 89 "Hdr.CRC", 90 pHeader->CRC32, 91 NULL ); 92 if ( EFI_ERROR ( Status )) { 93 break; 94 } 95 96 /// 97 /// Reserved field that must be set to 0. 98 /// 99 Status = RowHexValue ( SocketFD, 100 pPort, 101 "Hdr.Reserved", 102 pHeader->Reserved, 103 NULL ); 104 break; 105 } 106 107 // 108 // Return the operation status 109 // 110 DBG_EXIT_STATUS ( Status ); 111 return Status; 112 } 113 114 115 /** 116 Display a row containing a decimal value 117 118 @param [in] SocketFD The socket's file descriptor to add to the list. 119 @param [in] pPort The WSDT_PORT structure address 120 @param [in] pName Address of a zero terminated name string 121 @param [in] Value The value to display 122 123 @retval EFI_SUCCESS The request was successfully processed 124 125 **/ 126 EFI_STATUS 127 RowDecimalValue ( 128 IN int SocketFD, 129 IN WSDT_PORT * pPort, 130 IN CONST CHAR8 * pName, 131 IN UINT64 Value 132 ) 133 { 134 EFI_STATUS Status; 135 136 DBG_ENTER ( ); 137 138 // 139 // Use for/break instead of goto 140 // 141 for ( ; ; ) { 142 Status = HttpSendAnsiString ( SocketFD, 143 pPort, 144 "<tr><td>" ); 145 if ( EFI_ERROR ( Status )) { 146 break; 147 } 148 Status = HttpSendAnsiString ( SocketFD, 149 pPort, 150 pName ); 151 if ( EFI_ERROR ( Status )) { 152 break; 153 } 154 Status = HttpSendAnsiString ( SocketFD, 155 pPort, 156 "</td><td><code>" ); 157 if ( EFI_ERROR ( Status )) { 158 break; 159 } 160 Status = HttpSendValue ( SocketFD, 161 pPort, 162 Value ); 163 if ( EFI_ERROR ( Status )) { 164 break; 165 } 166 Status = HttpSendAnsiString ( SocketFD, 167 pPort, 168 "</code></td></tr>\r\n" ); 169 break; 170 } 171 172 // 173 // Return the operation status 174 // 175 DBG_EXIT_STATUS ( Status ); 176 return Status; 177 } 178 179 180 /** 181 Display a row containing a hex value 182 183 @param [in] SocketFD The socket's file descriptor to add to the list. 184 @param [in] pPort The WSDT_PORT structure address 185 @param [in] pName Address of a zero terminated name string 186 @param [in] Value The value to display 187 @param [in] pWebPage Address of a zero terminated web page name 188 189 @retval EFI_SUCCESS The request was successfully processed 190 191 **/ 192 EFI_STATUS 193 RowHexValue ( 194 IN int SocketFD, 195 IN WSDT_PORT * pPort, 196 IN CONST CHAR8 * pName, 197 IN UINT64 Value, 198 IN CONST CHAR16 * pWebPage 199 ) 200 { 201 EFI_STATUS Status; 202 203 DBG_ENTER ( ); 204 205 // 206 // Use for/break instead of goto 207 // 208 for ( ; ; ) { 209 Status = HttpSendAnsiString ( SocketFD, 210 pPort, 211 "<tr><td>" ); 212 if ( EFI_ERROR ( Status )) { 213 break; 214 } 215 Status = HttpSendAnsiString ( SocketFD, 216 pPort, 217 pName ); 218 if ( EFI_ERROR ( Status )) { 219 break; 220 } 221 Status = HttpSendAnsiString ( SocketFD, 222 pPort, 223 "</td><td><code>0x" ); 224 if ( EFI_ERROR ( Status )) { 225 break; 226 } 227 if ( NULL != pWebPage ) { 228 Status = HttpSendAnsiString ( SocketFD, 229 pPort, 230 "<a target=\"_blank\" href=\"" ); 231 if ( EFI_ERROR ( Status )) { 232 break; 233 } 234 Status = HttpSendUnicodeString ( SocketFD, 235 pPort, 236 pWebPage ); 237 if ( EFI_ERROR ( Status )) { 238 break; 239 } 240 Status = HttpSendAnsiString ( SocketFD, 241 pPort, 242 "\">" ); 243 if ( EFI_ERROR ( Status )) { 244 break; 245 } 246 } 247 Status = HttpSendHexValue ( SocketFD, 248 pPort, 249 Value ); 250 if ( EFI_ERROR ( Status )) { 251 break; 252 } 253 if ( NULL != pWebPage ) { 254 Status = HttpSendAnsiString ( SocketFD, 255 pPort, 256 "</a>" ); 257 if ( EFI_ERROR ( Status )) { 258 break; 259 } 260 } 261 Status = HttpSendAnsiString ( SocketFD, 262 pPort, 263 "</code></td></tr>\r\n" ); 264 break; 265 } 266 267 // 268 // Return the operation status 269 // 270 DBG_EXIT_STATUS ( Status ); 271 return Status; 272 } 273 274 275 /** 276 Display a row containing a pointer 277 278 @param [in] SocketFD The socket's file descriptor to add to the list. 279 @param [in] pPort The WSDT_PORT structure address 280 @param [in] pName Address of a zero terminated name string 281 @param [in] pAddress The address to display 282 @param [in] pWebPage Address of a zero terminated web page name 283 284 @retval EFI_SUCCESS The request was successfully processed 285 286 **/ 287 EFI_STATUS 288 RowPointer ( 289 IN int SocketFD, 290 IN WSDT_PORT * pPort, 291 IN CONST CHAR8 * pName, 292 IN CONST VOID * pAddress, 293 IN CONST CHAR16 * pWebPage 294 ) 295 { 296 EFI_STATUS Status; 297 298 DBG_ENTER ( ); 299 300 // 301 // Use for/break instead of goto 302 // 303 for ( ; ; ) { 304 Status = HttpSendAnsiString ( SocketFD, 305 pPort, 306 "<tr><td>" ); 307 if ( EFI_ERROR ( Status )) { 308 break; 309 } 310 Status = HttpSendAnsiString ( SocketFD, 311 pPort, 312 pName ); 313 if ( EFI_ERROR ( Status )) { 314 break; 315 } 316 Status = HttpSendAnsiString ( SocketFD, 317 pPort, 318 "</td><td><code>" ); 319 if ( EFI_ERROR ( Status )) { 320 break; 321 } 322 if ( NULL != pWebPage ) { 323 Status = HttpSendAnsiString ( SocketFD, 324 pPort, 325 "<a target=\"_blank\" href=\"" ); 326 if ( EFI_ERROR ( Status )) { 327 break; 328 } 329 Status = HttpSendUnicodeString ( SocketFD, 330 pPort, 331 pWebPage ); 332 if ( EFI_ERROR ( Status )) { 333 break; 334 } 335 Status = HttpSendAnsiString ( SocketFD, 336 pPort, 337 "\">" ); 338 if ( EFI_ERROR ( Status )) { 339 break; 340 } 341 } 342 Status = HttpSendAnsiString ( SocketFD, 343 pPort, 344 "0x" ); 345 if ( EFI_ERROR ( Status )) { 346 break; 347 } 348 Status = HttpSendHexBits ( SocketFD, 349 pPort, 350 sizeof ( pAddress ) * 8, 351 (UINT64)(UINTN)pAddress ); 352 if ( EFI_ERROR ( Status )) { 353 break; 354 } 355 if ( NULL != pWebPage ) { 356 Status = HttpSendAnsiString ( SocketFD, 357 pPort, 358 "</a>" ); 359 if ( EFI_ERROR ( Status )) { 360 break; 361 } 362 } 363 Status = HttpSendAnsiString ( SocketFD, 364 pPort, 365 "</code></td></tr>\r\n" ); 366 break; 367 } 368 369 // 370 // Return the operation status 371 // 372 DBG_EXIT_STATUS ( Status ); 373 return Status; 374 } 375 376 377 /** 378 Display a row containing a revision 379 380 @param [in] SocketFD The socket's file descriptor to add to the list. 381 @param [in] pPort The WSDT_PORT structure address 382 @param [in] pName Address of a zero terminated name string 383 @param [in] Revision The revision to display 384 385 @retval EFI_SUCCESS The request was successfully processed 386 387 **/ 388 EFI_STATUS 389 RowRevision ( 390 IN int SocketFD, 391 IN WSDT_PORT * pPort, 392 IN CONST CHAR8 * pName, 393 IN UINT32 Revision 394 ) 395 { 396 EFI_STATUS Status; 397 398 DBG_ENTER ( ); 399 400 // 401 // Use for/break instead of goto 402 // 403 for ( ; ; ) { 404 Status = HttpSendAnsiString ( SocketFD, 405 pPort, 406 "<tr><td>" ); 407 if ( EFI_ERROR ( Status )) { 408 break; 409 } 410 Status = HttpSendAnsiString ( SocketFD, 411 pPort, 412 pName ); 413 if ( EFI_ERROR ( Status )) { 414 break; 415 } 416 Status = HttpSendAnsiString ( SocketFD, 417 pPort, 418 "</td><td><code>" ); 419 if ( EFI_ERROR ( Status )) { 420 break; 421 } 422 Status = HttpSendValue ( SocketFD, 423 pPort, 424 Revision >> 16 ); 425 if ( EFI_ERROR ( Status )) { 426 break; 427 } 428 Status = HttpSendByte ( SocketFD, 429 pPort, 430 '.' ); 431 if ( EFI_ERROR ( Status )) { 432 break; 433 } 434 Status = HttpSendValue ( SocketFD, 435 pPort, 436 Revision & 0xFFFF ); 437 if ( EFI_ERROR ( Status )) { 438 break; 439 } 440 Status = HttpSendAnsiString ( SocketFD, 441 pPort, 442 "</code></td></tr>\r\n" ); 443 break; 444 } 445 446 // 447 // Return the operation status 448 // 449 DBG_EXIT_STATUS ( Status ); 450 return Status; 451 } 452 453 454 /** 455 Display a row containing a unicode string 456 457 @param [in] SocketFD The socket's file descriptor to add to the list. 458 @param [in] pPort The WSDT_PORT structure address 459 @param [in] pName Address of a zero terminated name string 460 @param [in] pString Address of a zero terminated unicode string 461 462 @retval EFI_SUCCESS The request was successfully processed 463 464 **/ 465 EFI_STATUS 466 RowUnicodeString ( 467 IN int SocketFD, 468 IN WSDT_PORT * pPort, 469 IN CONST CHAR8 * pName, 470 IN CONST CHAR16 * pString 471 ) 472 { 473 EFI_STATUS Status; 474 475 DBG_ENTER ( ); 476 477 // 478 // Use for/break instead of goto 479 // 480 for ( ; ; ) { 481 Status = HttpSendAnsiString ( SocketFD, 482 pPort, 483 "<tr><td>" ); 484 if ( EFI_ERROR ( Status )) { 485 break; 486 } 487 Status = HttpSendAnsiString ( SocketFD, 488 pPort, 489 pName ); 490 if ( EFI_ERROR ( Status )) { 491 break; 492 } 493 Status = HttpSendAnsiString ( SocketFD, 494 pPort, 495 "</td><td>" ); 496 if ( EFI_ERROR ( Status )) { 497 break; 498 } 499 Status = HttpSendUnicodeString ( SocketFD, 500 pPort, 501 pString ); 502 if ( EFI_ERROR ( Status )) { 503 break; 504 } 505 Status = HttpSendAnsiString ( SocketFD, 506 pPort, 507 "</td></tr>\r\n" ); 508 break; 509 } 510 511 // 512 // Return the operation status 513 // 514 DBG_EXIT_STATUS ( Status ); 515 return Status; 516 } 517 518 519 /** 520 Start the table page 521 522 @param [in] SocketFD The socket's file descriptor to add to the list. 523 @param [in] pPort The WSDT_PORT structure address 524 @param [in] pName Address of a zero terminated name string 525 @param [in] pTable Address of the table 526 527 @retval EFI_SUCCESS The request was successfully processed 528 529 **/ 530 EFI_STATUS 531 TableHeader ( 532 IN int SocketFD, 533 IN WSDT_PORT * pPort, 534 IN CONST CHAR16 * pName, 535 IN CONST VOID * pTable 536 ) 537 { 538 EFI_STATUS Status; 539 540 DBG_ENTER ( ); 541 542 // 543 // Use for/break instead of goto 544 // 545 for ( ; ; ) { 546 // 547 // Send the page header 548 // 549 Status = HttpPageHeader ( SocketFD, pPort, pName ); 550 if ( EFI_ERROR ( Status )) { 551 break; 552 } 553 554 // 555 // Build the table header 556 // 557 Status = HttpSendAnsiString ( SocketFD, 558 pPort, 559 "<h1>" ); 560 if ( EFI_ERROR ( Status )) { 561 break; 562 } 563 Status = HttpSendUnicodeString ( SocketFD, 564 pPort, 565 pName ); 566 if ( EFI_ERROR ( Status )) { 567 break; 568 } 569 if ( NULL != pTable ) { 570 Status = HttpSendAnsiString ( SocketFD, 571 pPort, 572 ": 0x" ); 573 if ( EFI_ERROR ( Status )) { 574 break; 575 } 576 Status = HttpSendHexBits ( SocketFD, 577 pPort, 578 sizeof ( pTable ) * 8, 579 (UINT64)(UINTN)pTable ); 580 if ( EFI_ERROR ( Status )) { 581 break; 582 } 583 } 584 Status = HttpSendAnsiString ( SocketFD, 585 pPort, 586 "</h1>\r\n" 587 "<table border=\"1\">\r\n" 588 " <tr bgcolor=\"c0c0ff\"><th>Field Name</th><th>Value</th></tr>\r\n" ); 589 break; 590 } 591 592 // 593 // Return the operation status 594 // 595 DBG_EXIT_STATUS ( Status ); 596 return Status; 597 } 598 599 600 /** 601 End the table page 602 603 @param [in] SocketFD The socket's file descriptor to add to the list. 604 @param [in] pPort The WSDT_PORT structure address 605 @param [out] pbDone Address to receive the request completion status 606 607 @retval EFI_SUCCESS The request was successfully processed 608 609 **/ 610 EFI_STATUS 611 TableTrailer ( 612 IN int SocketFD, 613 IN WSDT_PORT * pPort, 614 OUT BOOLEAN *pbDone 615 ) 616 { 617 EFI_STATUS Status; 618 619 DBG_ENTER ( ); 620 621 // 622 // Use for/break instead of goto 623 // 624 for ( ; ; ) { 625 // 626 // Build the table trailer 627 // 628 Status = HttpSendAnsiString ( SocketFD, 629 pPort, 630 "</table>\r\n" ); 631 if ( EFI_ERROR ( Status )) { 632 break; 633 } 634 635 // 636 // Send the page trailer 637 // 638 Status = HttpPageTrailer ( SocketFD, pPort, pbDone ); 639 break; 640 } 641 642 // 643 // Return the operation status 644 // 645 DBG_EXIT_STATUS ( Status ); 646 return Status; 647 } 648 649 650 /** 651 Respond with the system table 652 653 @param [in] SocketFD The socket's file descriptor to add to the list. 654 @param [in] pPort The WSDT_PORT structure address 655 @param [out] pbDone Address to receive the request completion status 656 657 @retval EFI_SUCCESS The request was successfully processed 658 659 **/ 660 EFI_STATUS 661 SystemTablePage ( 662 IN int SocketFD, 663 IN WSDT_PORT * pPort, 664 OUT BOOLEAN * pbDone 665 ) 666 { 667 EFI_STATUS Status; 668 669 DBG_ENTER ( ); 670 671 // 672 // Send the system table page 673 // 674 for ( ; ; ) { 675 // 676 // Send the page and table header 677 // 678 Status = TableHeader ( SocketFD, pPort, L"System Table", gST ); 679 if ( EFI_ERROR ( Status )) { 680 break; 681 } 682 683 /// 684 /// The table header for the EFI System Table. 685 /// 686 Status = EfiTableHeader ( SocketFD, 687 pPort, 688 &gST->Hdr ); 689 if ( EFI_ERROR ( Status )) { 690 break; 691 } 692 693 /// 694 /// A pointer to a null terminated string that identifies the vendor 695 /// that produces the system firmware for the platform. 696 /// 697 Status = RowUnicodeString ( SocketFD, 698 pPort, 699 "FirmwareVendor", 700 gST->FirmwareVendor ); 701 if ( EFI_ERROR ( Status )) { 702 break; 703 } 704 705 /// 706 /// A firmware vendor specific value that identifies the revision 707 /// of the system firmware for the platform. 708 /// 709 Status = RowRevision ( SocketFD, 710 pPort, 711 "FirmwareRevision", 712 gST->FirmwareRevision ); 713 if ( EFI_ERROR ( Status )) { 714 break; 715 } 716 717 /// 718 /// The handle for the active console input device. This handle must support 719 /// EFI_SIMPLE_TEXT_INPUT_PROTOCOL and EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL. 720 /// 721 Status = RowPointer ( SocketFD, 722 pPort, 723 "ConsoleInHandle", 724 (VOID *)gST->ConsoleInHandle, 725 NULL ); 726 if ( EFI_ERROR ( Status )) { 727 break; 728 } 729 730 /// 731 /// A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL interface that is 732 /// associated with ConsoleInHandle. 733 /// 734 Status = RowPointer ( SocketFD, 735 pPort, 736 "ConIn", 737 (VOID *)gST->ConIn, 738 NULL ); 739 if ( EFI_ERROR ( Status )) { 740 break; 741 } 742 743 /// 744 /// The handle for the active console output device. 745 /// 746 Status = RowPointer ( SocketFD, 747 pPort, 748 "ConsoleOutHandle", 749 (VOID *)gST->ConsoleOutHandle, 750 NULL ); 751 if ( EFI_ERROR ( Status )) { 752 break; 753 } 754 755 /// 756 /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface 757 /// that is associated with ConsoleOutHandle. 758 /// 759 Status = RowPointer ( SocketFD, 760 pPort, 761 "ConOut", 762 (VOID *)gST->ConOut, 763 NULL ); 764 if ( EFI_ERROR ( Status )) { 765 break; 766 } 767 768 /// 769 /// The handle for the active standard error console device. 770 /// This handle must support the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. 771 /// 772 Status = RowPointer ( SocketFD, 773 pPort, 774 "StandardErrorHandle", 775 (VOID *)gST->StandardErrorHandle, 776 NULL ); 777 if ( EFI_ERROR ( Status )) { 778 break; 779 } 780 781 /// 782 /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface 783 /// that is associated with StandardErrorHandle. 784 /// 785 Status = RowPointer ( SocketFD, 786 pPort, 787 "StdErr", 788 (VOID *)gST->StdErr, 789 NULL ); 790 if ( EFI_ERROR ( Status )) { 791 break; 792 } 793 794 /// 795 /// A pointer to the EFI Runtime Services Table. 796 /// 797 Status = RowPointer ( SocketFD, 798 pPort, 799 "RuntimeServices", 800 (VOID *)gST->RuntimeServices, 801 PAGE_RUNTIME_SERVICES_TABLE ); 802 803 /// 804 /// A pointer to the EFI Boot Services Table. 805 /// 806 Status = RowPointer ( SocketFD, 807 pPort, 808 "BootServices", 809 (VOID *)gST->BootServices, 810 PAGE_BOOT_SERVICES_TABLE ); 811 if ( EFI_ERROR ( Status )) { 812 break; 813 } 814 815 /// 816 /// The number of system configuration tables in the buffer ConfigurationTable. 817 /// 818 Status = RowDecimalValue ( SocketFD, 819 pPort, 820 "NumberOfTableEntries", 821 gST->NumberOfTableEntries ); 822 if ( EFI_ERROR ( Status )) { 823 break; 824 } 825 826 /// 827 /// A pointer to the system configuration tables. 828 /// The number of entries in the table is NumberOfTableEntries. 829 /// 830 Status = RowPointer ( SocketFD, 831 pPort, 832 "ConfigurationTable", 833 (VOID *)gST->ConfigurationTable, 834 PAGE_CONFIGURATION_TABLE ); 835 if ( EFI_ERROR ( Status )) { 836 break; 837 } 838 839 // 840 // Build the table trailer 841 // 842 Status = TableTrailer ( SocketFD, 843 pPort, 844 pbDone ); 845 break; 846 } 847 848 // 849 // Return the operation status 850 // 851 DBG_EXIT_STATUS ( Status ); 852 return Status; 853 } 854