1 /** 2 @file 3 Display the memory type range registers 4 5 Copyright (c) 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 #include <Library/MtrrLib.h> 18 19 #define VARIABLE_MTRR_VALID 0x800 20 21 CONST char * mMemoryType [ ] = { 22 "Uncached", 23 "Write Combining", 24 "Reserved", 25 "Reserved", 26 "Write Through", 27 "Write Protected", 28 "Writeback" 29 }; 30 31 32 /** 33 Display a fixed MTRR row 34 35 @param [in] SocketFD The socket's file descriptor to add to the list. 36 @param [in] pPort The WSDT_PORT structure address 37 @param [in] Start Start address for the region 38 @param [in] End End address for the region 39 @param [in] Type Memory type 40 41 @retval EFI_SUCCESS The request was successfully processed 42 43 **/ 44 EFI_STATUS 45 MtrrDisplayFixedRow ( 46 IN int SocketFD, 47 IN WSDT_PORT * pPort, 48 IN UINT64 Start, 49 IN UINT64 End, 50 IN UINT64 Type 51 ) 52 { 53 EFI_STATUS Status; 54 55 // 56 // Use break instead of goto 57 // 58 for ( ; ; ) { 59 // 60 // Start the row 61 // 62 Status = HttpSendAnsiString ( SocketFD, 63 pPort, 64 " <tr><td align=\"right\"><code>0x" ); 65 if ( EFI_ERROR ( Status )) { 66 break; 67 } 68 69 // 70 // Start 71 // 72 Status = HttpSendHexValue ( SocketFD, 73 pPort, 74 Start ); 75 if ( EFI_ERROR ( Status )) { 76 break; 77 } 78 79 // 80 // End 81 // 82 Status = HttpSendAnsiString ( SocketFD, 83 pPort, 84 "</code></td><td align=\"right\"><code>0x" ); 85 if ( EFI_ERROR ( Status )) { 86 break; 87 } 88 Status = HttpSendHexValue ( SocketFD, 89 pPort, 90 End - 1 ); 91 if ( EFI_ERROR ( Status )) { 92 break; 93 } 94 95 // 96 // Type 97 // 98 Status = HttpSendAnsiString ( SocketFD, 99 pPort, 100 "</code></td><td>" ); 101 if ( EFI_ERROR ( Status )) { 102 break; 103 } 104 Type &= 0xff; 105 Status = HttpSendAnsiString ( SocketFD, 106 pPort, 107 ( DIM ( mMemoryType ) > Type ) 108 ? mMemoryType [ Type ] 109 : "Reserved" ); 110 if ( EFI_ERROR ( Status )) { 111 break; 112 } 113 114 // 115 // End of row 116 // 117 Status = HttpSendAnsiString ( SocketFD, 118 pPort, 119 "</td></tr>\r\n" ); 120 break; 121 } 122 123 // 124 // Return the final status 125 // 126 return Status; 127 } 128 129 130 /** 131 Display the memory type registers 132 133 @param [in] SocketFD The socket's file descriptor to add to the list. 134 @param [in] pPort The WSDT_PORT structure address 135 @param [out] pbDone Address to receive the request completion status 136 137 @retval EFI_SUCCESS The request was successfully processed 138 139 **/ 140 EFI_STATUS 141 MemoryTypeRegistersPage ( 142 IN int SocketFD, 143 IN WSDT_PORT * pPort, 144 OUT BOOLEAN * pbDone 145 ) 146 { 147 UINT64 Addr; 148 BOOLEAN bValid; 149 UINT64 Capabilities; 150 UINTN Count; 151 UINT64 DefType; 152 UINTN Index; 153 UINT64 Mask; 154 UINT64 MaxMtrrs; 155 CONST UINT64 mFixedAddresses [( 8 * MTRR_NUMBER_OF_FIXED_MTRR ) + 1 ] = { 156 0ULL, 157 0x10000ULL, 158 0x20000ULL, 159 0x30000ULL, 160 0x40000ULL, 161 0x50000ULL, 162 0x60000ULL, 163 0x70000ULL, 164 165 0x80000ULL, 166 0x84000ULL, 167 0x88000ULL, 168 0x8c000ULL, 169 0x90000ULL, 170 0x94000ULL, 171 0x98000ULL, 172 0x9c000ULL, 173 174 0xa0000ULL, 175 0xa4000ULL, 176 0xa8000ULL, 177 0xac000ULL, 178 0xb0000ULL, 179 0xb4000ULL, 180 0xb8000ULL, 181 0xbc000ULL, 182 183 0xc0000ULL, 184 0xc1000ULL, 185 0xc2000ULL, 186 0xc3000ULL, 187 0xc4000ULL, 188 0xc5000ULL, 189 0xc6000ULL, 190 0xc7000ULL, 191 192 0xc8000ULL, 193 0xc9000ULL, 194 0xca000ULL, 195 0xcb000ULL, 196 0xcc000ULL, 197 0xcd000ULL, 198 0xce000ULL, 199 0xcf000ULL, 200 201 0xd0000ULL, 202 0xd1000ULL, 203 0xd2000ULL, 204 0xd3000ULL, 205 0xd4000ULL, 206 0xd5000ULL, 207 0xd6000ULL, 208 0xd7000ULL, 209 210 0xd8000ULL, 211 0xd9000ULL, 212 0xda000ULL, 213 0xdb000ULL, 214 0xdc000ULL, 215 0xdd000ULL, 216 0xde000ULL, 217 0xdf000ULL, 218 219 0xe0000ULL, 220 0xe1000ULL, 221 0xe2000ULL, 222 0xe3000ULL, 223 0xe4000ULL, 224 0xe5000ULL, 225 0xe6000ULL, 226 0xe7000ULL, 227 228 0xe8000ULL, 229 0xe9000ULL, 230 0xea000ULL, 231 0xeb000ULL, 232 0xec000ULL, 233 0xed000ULL, 234 0xee000ULL, 235 0xef000ULL, 236 237 0xf0000ULL, 238 0xf1000ULL, 239 0xf2000ULL, 240 0xf3000ULL, 241 0xf4000ULL, 242 0xf5000ULL, 243 0xf6000ULL, 244 0xf7000ULL, 245 246 0xf8000ULL, 247 0xf9000ULL, 248 0xfa000ULL, 249 0xfb000ULL, 250 0xfc000ULL, 251 0xfd000ULL, 252 0xfe000ULL, 253 0xff000ULL, 254 255 0x100000ULL 256 }; 257 MTRR_SETTINGS Mtrr; 258 CONST UINT64 * pMemEnd; 259 CONST UINT64 * pMemStart; 260 UINT64 PreviousType; 261 UINT64 ShiftCount; 262 EFI_STATUS Status; 263 UINT64 Type; 264 INT64 Value; 265 266 DBG_ENTER ( ); 267 268 // 269 // Send the Memory Type Registers page 270 // 271 for ( ; ; ) { 272 // 273 // Send the page header 274 // 275 Status = HttpPageHeader ( SocketFD, pPort, L"Memory Type Range Registers" ); 276 if ( EFI_ERROR ( Status )) { 277 break; 278 } 279 280 // 281 // Send the header 282 // 283 Status = HttpSendAnsiString ( SocketFD, 284 pPort, 285 "<h1>Memory Type Range Registers</h1>\r\n" ); 286 if ( EFI_ERROR ( Status )) { 287 break; 288 } 289 290 // 291 // Determine if MTRRs are supported 292 // 293 if ( !IsMtrrSupported ( )) { 294 Status = HttpSendAnsiString ( SocketFD, 295 pPort, 296 "<p>Memory Type Range Registers are not supported!\r\n" ); 297 if ( EFI_ERROR ( Status )) { 298 break; 299 } 300 } 301 else { 302 // 303 // Get the capabilities 304 // 305 Capabilities = AsmReadMsr64 ( MTRR_LIB_IA32_MTRR_CAP ); 306 DefType = AsmReadMsr64 ( MTRR_LIB_IA32_MTRR_DEF_TYPE ); 307 308 // 309 // Display the capabilities 310 // 311 Status = HttpSendAnsiString ( SocketFD, 312 pPort, 313 "<p>Capabilities: " ); 314 if ( EFI_ERROR ( Status )) { 315 break; 316 } 317 Status = HttpSendHexValue ( SocketFD, 318 pPort, 319 Capabilities ); 320 if ( EFI_ERROR ( Status )) { 321 break; 322 } 323 Status = HttpSendAnsiString ( SocketFD, 324 pPort, 325 "<br>\r\n" ); 326 if ( EFI_ERROR ( Status )) { 327 break; 328 } 329 330 // 331 // Display the default type 332 // 333 Status = HttpSendAnsiString ( SocketFD, 334 pPort, 335 "Def Type: " ); 336 if ( EFI_ERROR ( Status )) { 337 break; 338 } 339 Status = HttpSendHexValue ( SocketFD, 340 pPort, 341 DefType ); 342 if ( EFI_ERROR ( Status )) { 343 break; 344 } 345 Status = HttpSendAnsiString ( SocketFD, 346 pPort, 347 ", MTRRs " ); 348 if ( EFI_ERROR ( Status )) { 349 break; 350 } 351 Status = HttpSendAnsiString ( SocketFD, 352 pPort, 353 ( 0 != ( DefType & MTRR_LIB_CACHE_MTRR_ENABLED )) 354 ? "Enabled" 355 : "Disabled" ); 356 if ( EFI_ERROR ( Status )) { 357 break; 358 } 359 Status = HttpSendAnsiString ( SocketFD, 360 pPort, 361 ", Fixed MTRRs " ); 362 if ( EFI_ERROR ( Status )) { 363 break; 364 } 365 Status = HttpSendAnsiString ( SocketFD, 366 pPort, 367 ( 0 != ( DefType & MTRR_LIB_CACHE_FIXED_MTRR_ENABLED )) 368 ? "Enabled" 369 : "Disabled" ); 370 if ( EFI_ERROR ( Status )) { 371 break; 372 } 373 Status = HttpSendAnsiString ( SocketFD, 374 pPort, 375 ", " ); 376 if ( EFI_ERROR ( Status )) { 377 break; 378 } 379 Type = DefType & 0xff; 380 Status = HttpSendAnsiString ( SocketFD, 381 pPort, 382 ( DIM ( mMemoryType ) > Type ) 383 ? mMemoryType [ Type ] 384 : "Reserved" ); 385 if ( EFI_ERROR ( Status )) { 386 break; 387 } 388 Status = HttpSendAnsiString ( SocketFD, 389 pPort, 390 "</p>\r\n" ); 391 if ( EFI_ERROR ( Status )) { 392 break; 393 } 394 395 // 396 // Determine if MTRRs are enabled 397 // 398 if ( 0 == ( DefType & MTRR_LIB_CACHE_MTRR_ENABLED )) { 399 Status = HttpSendAnsiString ( SocketFD, 400 pPort, 401 "<p>All memory is uncached!</p>\r\n" ); 402 if ( EFI_ERROR ( Status )) { 403 break; 404 } 405 } 406 else { 407 // 408 // Get the MTRRs 409 // 410 MtrrGetAllMtrrs ( &Mtrr ); 411 412 // 413 // Determine if the fixed MTRRs are supported 414 // 415 if (( 0 != ( Capabilities & 0x100 )) 416 && ( 0 != ( DefType & MTRR_LIB_CACHE_FIXED_MTRR_ENABLED ))) { 417 418 // 419 // Beginning of table 420 // 421 Status = HttpSendAnsiString ( SocketFD, 422 pPort, 423 "<h2>Fixed MTRRs</h2>\r\n" 424 "<table>\r\n" 425 " <tr><th>Index</th><th align=\"right\">Value</th><th align=\"right\">Start</th><th align=\"right\">End</th></tr>\r\n" ); 426 if ( EFI_ERROR ( Status )) { 427 break; 428 } 429 430 // 431 // Display the fixed MTRRs 432 // 433 pMemStart = &mFixedAddresses[ 0 ]; 434 for ( Count = 0; DIM ( Mtrr.Fixed.Mtrr ) > Count; Count++ ) { 435 // 436 // Start the row 437 // 438 Status = HttpSendAnsiString ( SocketFD, 439 pPort, 440 " <tr><td>" ); 441 if ( EFI_ERROR ( Status )) { 442 break; 443 } 444 445 // 446 // Index 447 // 448 Status = HttpSendValue ( SocketFD, 449 pPort, 450 Count ); 451 if ( EFI_ERROR ( Status )) { 452 break; 453 } 454 455 // 456 // Value 457 // 458 Status = HttpSendAnsiString ( SocketFD, 459 pPort, 460 "</td><td align=\"right\"><code>0x" ); 461 if ( EFI_ERROR ( Status )) { 462 break; 463 } 464 Status = HttpSendHexValue ( SocketFD, 465 pPort, 466 Mtrr.Fixed.Mtrr[ Count ]); 467 if ( EFI_ERROR ( Status )) { 468 break; 469 } 470 471 // 472 // Start 473 // 474 Status = HttpSendAnsiString ( SocketFD, 475 pPort, 476 "</code></td><td align=\"right\"><code>0x" ); 477 if ( EFI_ERROR ( Status )) { 478 break; 479 } 480 Status = HttpSendHexValue ( SocketFD, 481 pPort, 482 *pMemStart ); 483 if ( EFI_ERROR ( Status )) { 484 break; 485 } 486 pMemStart += 8; 487 488 // 489 // Value 490 // 491 Status = HttpSendAnsiString ( SocketFD, 492 pPort, 493 "</code></td><td align=\"right\"><code>0x" ); 494 if ( EFI_ERROR ( Status )) { 495 break; 496 } 497 Status = HttpSendHexValue ( SocketFD, 498 pPort, 499 *pMemStart - 1 ); 500 if ( EFI_ERROR ( Status )) { 501 break; 502 } 503 504 // 505 // End of row 506 // 507 Status = HttpSendAnsiString ( SocketFD, 508 pPort, 509 "</code></td></tr>\r\n" ); 510 if ( EFI_ERROR ( Status )) { 511 break; 512 } 513 } 514 if ( EFI_ERROR ( Status )) { 515 break; 516 } 517 518 // 519 // End of table 520 // 521 Status = HttpSendAnsiString ( SocketFD, 522 pPort, 523 "</table>\r\n" ); 524 if ( EFI_ERROR ( Status )) { 525 break; 526 } 527 528 // 529 // Beginning of table 530 // 531 Status = HttpSendAnsiString ( SocketFD, 532 pPort, 533 "<table>\r\n" 534 " <tr><th align=\"right\">Start</th><th align=\"right\">End</th><th align=\"left\">Type</th></tr>\r\n" ); 535 if ( EFI_ERROR ( Status )) { 536 break; 537 } 538 539 // 540 // Decode the fixed MTRRs 541 // 542 PreviousType = Mtrr.Fixed.Mtrr[ 0 ] & 0xff; 543 pMemStart = &mFixedAddresses[ 0 ]; 544 pMemEnd = pMemStart; 545 for ( Count = 0; DIM ( Mtrr.Fixed.Mtrr ) > Count; Count++ ) { 546 // 547 // Get the memory types 548 // 549 Type = Mtrr.Fixed.Mtrr[ Count ]; 550 551 // 552 // Walk the memory range 553 // 554 for ( Index = 0; 8 > Index; Index++ ) { 555 // 556 // Determine if this is the same memory type 557 // 558 if ( PreviousType != ( Type & 0xff )) { 559 // 560 // Display the row 561 // 562 Status = MtrrDisplayFixedRow ( SocketFD, 563 pPort, 564 *pMemStart, 565 *pMemEnd, 566 PreviousType ); 567 if ( EFI_ERROR ( Status )) { 568 break; 569 } 570 571 // 572 // Start the next range of addresses 573 // 574 pMemStart = pMemEnd; 575 PreviousType = Type & 0xff; 576 } 577 578 // 579 // Set the next memory range and type 580 // 581 Type >>= 8; 582 pMemEnd += 1; 583 } 584 if ( EFI_ERROR ( Status )) { 585 break; 586 } 587 } 588 if ( EFI_ERROR ( Status )) { 589 break; 590 } 591 592 // 593 // Display the final row 594 // 595 Status = MtrrDisplayFixedRow ( SocketFD, 596 pPort, 597 *pMemStart, 598 *pMemEnd, 599 PreviousType ); 600 if ( EFI_ERROR ( Status )) { 601 break; 602 } 603 604 // 605 // End of table 606 // 607 Status = HttpSendAnsiString ( SocketFD, 608 pPort, 609 "</table>\r\n" ); 610 if ( EFI_ERROR ( Status )) { 611 break; 612 } 613 } 614 615 // 616 // Determine if the variable MTRRs are supported 617 // 618 MaxMtrrs = Capabilities & MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK; 619 if ( 0 < MaxMtrrs ) { 620 // 621 // Beginning of table 622 // 623 Status = HttpSendAnsiString ( SocketFD, 624 pPort, 625 "<h2>Variable MTRRs</h2>\r\n" 626 "<table>\r\n" 627 " <tr><th>Index</th><th align=\"right\">Base</th><th align=\"right\">Mask</th><th align=\"right\">Start</th><th align=\"right\">End</th></tr>\r\n" ); 628 if ( EFI_ERROR ( Status )) { 629 break; 630 } 631 632 // 633 // Display the variable MTRRs 634 // 635 for ( Count = 0; MaxMtrrs > Count; Count++ ) { 636 // 637 // Start the row 638 // 639 Status = HttpSendAnsiString ( SocketFD, 640 pPort, 641 " <tr><td>" ); 642 if ( EFI_ERROR ( Status )) { 643 break; 644 } 645 646 // 647 // Index 648 // 649 Status = HttpSendValue ( SocketFD, 650 pPort, 651 Count ); 652 if ( EFI_ERROR ( Status )) { 653 break; 654 } 655 656 // 657 // Base 658 // 659 Status = HttpSendAnsiString ( SocketFD, 660 pPort, 661 "</td><td align=\"right\"><code>0x" ); 662 if ( EFI_ERROR ( Status )) { 663 break; 664 } 665 Status = HttpSendHexValue ( SocketFD, 666 pPort, 667 Mtrr.Variables.Mtrr[ Count ].Base ); 668 if ( EFI_ERROR ( Status )) { 669 break; 670 } 671 672 // 673 // Mask 674 // 675 Status = HttpSendAnsiString ( SocketFD, 676 pPort, 677 "</td><td align=\"right\"><code>0x" ); 678 if ( EFI_ERROR ( Status )) { 679 break; 680 } 681 Status = HttpSendHexValue ( SocketFD, 682 pPort, 683 Mtrr.Variables.Mtrr[ Count ].Mask ); 684 if ( EFI_ERROR ( Status )) { 685 break; 686 } 687 688 // 689 // Determine if the entry is valid 690 // 691 bValid = ( Mtrr.Variables.Mtrr[ Count ].Mask & VARIABLE_MTRR_VALID ) ? TRUE : FALSE; 692 693 // 694 // Start 695 // 696 Status = HttpSendAnsiString ( SocketFD, 697 pPort, 698 "</code></td><td align=\"right\"><code>" ); 699 if ( EFI_ERROR ( Status )) { 700 break; 701 } 702 Addr = Mtrr.Variables.Mtrr[ Count ].Base & 0xfffffffffffff000ULL; 703 if ( bValid ) { 704 Status = HttpSendAnsiString ( SocketFD, 705 pPort, 706 "0x" ); 707 if ( EFI_ERROR ( Status )) { 708 break; 709 } 710 Status = HttpSendHexValue ( SocketFD, 711 pPort, 712 Addr ); 713 } 714 else { 715 Status = HttpSendAnsiString ( SocketFD, 716 pPort, 717 "Invalid" ); 718 } 719 if ( EFI_ERROR ( Status )) { 720 break; 721 } 722 723 // 724 // End 725 // 726 Status = HttpSendAnsiString ( SocketFD, 727 pPort, 728 "</code></td><td align=\"right\"><code>" ); 729 if ( EFI_ERROR ( Status )) { 730 break; 731 } 732 if ( bValid ) { 733 // 734 // Determine the end address 735 // 736 Mask = Mtrr.Variables.Mtrr[ Count ].Mask; 737 Value = Mask; 738 ShiftCount = 0; 739 while ( 0 < Value ) { 740 Value <<= 1; 741 ShiftCount += 1; 742 } 743 Value = 1; 744 Value <<= 64 - ShiftCount; 745 Value -= 1; 746 Value = ~Value; 747 Value |= Mask; 748 Value &= ~VARIABLE_MTRR_VALID; 749 Value = ~Value; 750 751 Status = HttpSendAnsiString ( SocketFD, 752 pPort, 753 "0x" ); 754 if ( EFI_ERROR ( Status )) { 755 break; 756 } 757 Status = HttpSendHexValue ( SocketFD, 758 pPort, 759 Addr + Value ); 760 } 761 if ( EFI_ERROR ( Status )) { 762 break; 763 } 764 765 // 766 // Type 767 // 768 Status = HttpSendAnsiString ( SocketFD, 769 pPort, 770 "</code></td><td>" ); 771 if ( EFI_ERROR ( Status )) { 772 break; 773 } 774 if ( bValid ) { 775 Type = Mtrr.Variables.Mtrr[ Count ].Base & 0xFF; 776 Status = HttpSendAnsiString ( SocketFD, 777 pPort, 778 ( DIM ( mMemoryType ) > Type ) 779 ? mMemoryType [ Type ] 780 : "Reserved" ); 781 } 782 if ( EFI_ERROR ( Status )) { 783 break; 784 } 785 786 // 787 // End of row 788 // 789 Status = HttpSendAnsiString ( SocketFD, 790 pPort, 791 "</td></tr>\r\n" ); 792 if ( EFI_ERROR ( Status )) { 793 break; 794 } 795 } 796 if ( EFI_ERROR ( Status )) { 797 break; 798 } 799 800 // 801 // End of table 802 // 803 Status = HttpSendAnsiString ( SocketFD, 804 pPort, 805 "</table>\r\n" ); 806 if ( EFI_ERROR ( Status )) { 807 break; 808 } 809 } 810 } 811 } 812 813 // 814 // Send the page trailer 815 // 816 Status = HttpPageTrailer ( SocketFD, pPort, pbDone ); 817 break; 818 } 819 820 // 821 // Return the operation status 822 // 823 DBG_EXIT_STATUS ( Status ); 824 return Status; 825 } 826