diff options
Diffstat (limited to 'AppPkg/Applications/Sockets/WebServer/Mtrr.c')
-rw-r--r-- | AppPkg/Applications/Sockets/WebServer/Mtrr.c | 825 |
1 files changed, 825 insertions, 0 deletions
diff --git a/AppPkg/Applications/Sockets/WebServer/Mtrr.c b/AppPkg/Applications/Sockets/WebServer/Mtrr.c new file mode 100644 index 0000000000..92f90b0ae0 --- /dev/null +++ b/AppPkg/Applications/Sockets/WebServer/Mtrr.c @@ -0,0 +1,825 @@ +/** + @file + Display the memory type range registers + + Copyright (c) 2012, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <WebServer.h> +#include <Library/MtrrLib.h> + +#define VARIABLE_MTRR_VALID 0x800 + +CONST char * mMemoryType [ ] = { + "Uncached", + "Write Combining", + "Reserved", + "Reserved", + "Write Through", + "Write Protected", + "Writeback" +}; + + +/** + Display a fixed MTRR row + + @param [in] SocketFD The socket's file descriptor to add to the list. + @param [in] pPort The WSDT_PORT structure address + @param [in] Start Start address for the region + @param [in] End End address for the region + @param [in] Type Memory type + + @retval EFI_SUCCESS The request was successfully processed + +**/ +EFI_STATUS +MtrrDisplayFixedRow ( + IN int SocketFD, + IN WSDT_PORT * pPort, + IN UINT64 Start, + IN UINT64 End, + IN UINT64 Type + ) +{ + EFI_STATUS Status; + + // + // Use break instead of goto + // + for ( ; ; ) { + // + // Start the row + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + " <tr><td align=\"right\"><code>0x" ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Start + // + Status = HttpSendHexValue ( SocketFD, + pPort, + Start ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // End + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "</code></td><td align=\"right\"><code>0x" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendHexValue ( SocketFD, + pPort, + End - 1 ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Type + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "</code></td><td>" ); + if ( EFI_ERROR ( Status )) { + break; + } + Type &= 0xff; + Status = HttpSendAnsiString ( SocketFD, + pPort, + ( DIM ( mMemoryType ) > Type ) + ? mMemoryType [ Type ] + : "Reserved" ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // End of row + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "</td></tr>\r\n" ); + break; + } + + // + // Return the final status + // + return Status; +} + + +/** + Display the memory type registers + + @param [in] SocketFD The socket's file descriptor to add to the list. + @param [in] pPort The WSDT_PORT structure address + @param [out] pbDone Address to receive the request completion status + + @retval EFI_SUCCESS The request was successfully processed + +**/ +EFI_STATUS +MemoryTypeRegistersPage ( + IN int SocketFD, + IN WSDT_PORT * pPort, + OUT BOOLEAN * pbDone + ) +{ + UINT64 Addr; + BOOLEAN bValid; + UINT64 Capabilities; + UINTN Count; + UINT64 DefType; + UINTN Index; + UINT64 Mask; + UINT64 MaxMtrrs; + CONST UINT64 mFixedAddresses [( 8 * MTRR_NUMBER_OF_FIXED_MTRR ) + 1 ] = { + 0ULL, + 0x10000ULL, + 0x20000ULL, + 0x30000ULL, + 0x40000ULL, + 0x50000ULL, + 0x60000ULL, + 0x70000ULL, + + 0x80000ULL, + 0x84000ULL, + 0x88000ULL, + 0x8c000ULL, + 0x90000ULL, + 0x94000ULL, + 0x98000ULL, + 0x9c000ULL, + + 0xa0000ULL, + 0xa4000ULL, + 0xa8000ULL, + 0xac000ULL, + 0xb0000ULL, + 0xb4000ULL, + 0xb8000ULL, + 0xbc000ULL, + + 0xc0000ULL, + 0xc1000ULL, + 0xc2000ULL, + 0xc3000ULL, + 0xc4000ULL, + 0xc5000ULL, + 0xc6000ULL, + 0xc7000ULL, + + 0xc8000ULL, + 0xc9000ULL, + 0xca000ULL, + 0xcb000ULL, + 0xcc000ULL, + 0xcd000ULL, + 0xce000ULL, + 0xcf000ULL, + + 0xd0000ULL, + 0xd1000ULL, + 0xd2000ULL, + 0xd3000ULL, + 0xd4000ULL, + 0xd5000ULL, + 0xd6000ULL, + 0xd7000ULL, + + 0xd8000ULL, + 0xd9000ULL, + 0xda000ULL, + 0xdb000ULL, + 0xdc000ULL, + 0xdd000ULL, + 0xde000ULL, + 0xdf000ULL, + + 0xe0000ULL, + 0xe1000ULL, + 0xe2000ULL, + 0xe3000ULL, + 0xe4000ULL, + 0xe5000ULL, + 0xe6000ULL, + 0xe7000ULL, + + 0xe8000ULL, + 0xe9000ULL, + 0xea000ULL, + 0xeb000ULL, + 0xec000ULL, + 0xed000ULL, + 0xee000ULL, + 0xef000ULL, + + 0xf0000ULL, + 0xf1000ULL, + 0xf2000ULL, + 0xf3000ULL, + 0xf4000ULL, + 0xf5000ULL, + 0xf6000ULL, + 0xf7000ULL, + + 0xf8000ULL, + 0xf9000ULL, + 0xfa000ULL, + 0xfb000ULL, + 0xfc000ULL, + 0xfd000ULL, + 0xfe000ULL, + 0xff000ULL, + + 0x100000ULL + }; + MTRR_SETTINGS Mtrr; + CONST UINT64 * pMemEnd; + CONST UINT64 * pMemStart; + UINT64 PreviousType; + UINT64 ShiftCount; + EFI_STATUS Status; + UINT64 Type; + INT64 Value; + + DBG_ENTER ( ); + + // + // Send the Memory Type Registers page + // + for ( ; ; ) { + // + // Send the page header + // + Status = HttpPageHeader ( SocketFD, pPort, L"Memory Type Range Registers" ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Send the header + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "<h1>Memory Type Range Registers</h1>\r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Determine if MTRRs are supported + // + if ( !IsMtrrSupported ( )) { + Status = HttpSendAnsiString ( SocketFD, + pPort, + "<p>Memory Type Range Registers are not supported!\r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + } + else { + // + // Get the capabilities + // + Capabilities = AsmReadMsr64 ( MTRR_LIB_IA32_MTRR_CAP ); + DefType = AsmReadMsr64 ( MTRR_LIB_IA32_MTRR_DEF_TYPE ); + + // + // Display the capabilities + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "<p>Capabilities: " ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendHexValue ( SocketFD, + pPort, + Capabilities ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendAnsiString ( SocketFD, + pPort, + "<br>\r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Display the default type + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "Def Type: " ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendHexValue ( SocketFD, + pPort, + DefType ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendAnsiString ( SocketFD, + pPort, + ", MTRRs " ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendAnsiString ( SocketFD, + pPort, + ( 0 != ( DefType & MTRR_LIB_CACHE_MTRR_ENABLED )) + ? "Enabled" + : "Disabled" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendAnsiString ( SocketFD, + pPort, + ", Fixed MTRRs " ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendAnsiString ( SocketFD, + pPort, + ( 0 != ( DefType & MTRR_LIB_CACHE_FIXED_MTRR_ENABLED )) + ? "Enabled" + : "Disabled" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendAnsiString ( SocketFD, + pPort, + ", " ); + if ( EFI_ERROR ( Status )) { + break; + } + Type = DefType & 0xff; + Status = HttpSendAnsiString ( SocketFD, + pPort, + ( DIM ( mMemoryType ) > Type ) + ? mMemoryType [ Type ] + : "Reserved" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendAnsiString ( SocketFD, + pPort, + "</p>\r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Determine if MTRRs are enabled + // + if ( 0 == ( DefType & MTRR_LIB_CACHE_MTRR_ENABLED )) { + Status = HttpSendAnsiString ( SocketFD, + pPort, + "<p>All memory is uncached!</p>\r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + } + else { + // + // Get the MTRRs + // + MtrrGetAllMtrrs ( &Mtrr ); + + // + // Determine if the fixed MTRRs are supported + // + if (( 0 != ( Capabilities & 0x100 )) + && ( 0 != ( DefType & MTRR_LIB_CACHE_FIXED_MTRR_ENABLED ))) { + + // + // Beginning of table + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "<h2>Fixed MTRRs</h2>\r\n" + "<table>\r\n" + " <tr><th>Index</th><th align=\"right\">Value</th><th align=\"right\">Start</th><th align=\"right\">End</th></tr>\r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Display the fixed MTRRs + // + pMemStart = &mFixedAddresses[ 0 ]; + for ( Count = 0; DIM ( Mtrr.Fixed.Mtrr ) > Count; Count++ ) { + // + // Start the row + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + " <tr><td>" ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Index + // + Status = HttpSendValue ( SocketFD, + pPort, + Count ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Value + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "</td><td align=\"right\"><code>0x" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendHexValue ( SocketFD, + pPort, + Mtrr.Fixed.Mtrr[ Count ]); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Start + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "</code></td><td align=\"right\"><code>0x" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendHexValue ( SocketFD, + pPort, + *pMemStart ); + if ( EFI_ERROR ( Status )) { + break; + } + pMemStart += 8; + + // + // Value + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "</code></td><td align=\"right\"><code>0x" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendHexValue ( SocketFD, + pPort, + *pMemStart - 1 ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // End of row + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "</code></td></tr>\r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + } + if ( EFI_ERROR ( Status )) { + break; + } + + // + // End of table + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "</table>\r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Beginning of table + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "<table>\r\n" + " <tr><th align=\"right\">Start</th><th align=\"right\">End</th><th align=\"left\">Type</th></tr>\r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Decode the fixed MTRRs + // + PreviousType = Mtrr.Fixed.Mtrr[ 0 ] & 0xff; + pMemStart = &mFixedAddresses[ 0 ]; + pMemEnd = pMemStart; + for ( Count = 0; DIM ( Mtrr.Fixed.Mtrr ) > Count; Count++ ) { + // + // Get the memory types + // + Type = Mtrr.Fixed.Mtrr[ Count ]; + + // + // Walk the memory range + // + for ( Index = 0; 8 > Index; Index++ ) { + // + // Determine if this is the same memory type + // + if ( PreviousType != ( Type & 0xff )) { + // + // Display the row + // + Status = MtrrDisplayFixedRow ( SocketFD, + pPort, + *pMemStart, + *pMemEnd, + PreviousType ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Start the next range of addresses + // + pMemStart = pMemEnd; + PreviousType = Type & 0xff; + } + + // + // Set the next memory range and type + // + Type >>= 8; + pMemEnd += 1; + } + if ( EFI_ERROR ( Status )) { + break; + } + } + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Display the final row + // + Status = MtrrDisplayFixedRow ( SocketFD, + pPort, + *pMemStart, + *pMemEnd, + PreviousType ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // End of table + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "</table>\r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + } + + // + // Determine if the variable MTRRs are supported + // + MaxMtrrs = Capabilities & MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK; + if ( 0 < MaxMtrrs ) { + // + // Beginning of table + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "<h2>Variable MTRRs</h2>\r\n" + "<table>\r\n" + " <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" ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Display the variable MTRRs + // + for ( Count = 0; MaxMtrrs > Count; Count++ ) { + // + // Start the row + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + " <tr><td>" ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Index + // + Status = HttpSendValue ( SocketFD, + pPort, + Count ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Base + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "</td><td align=\"right\"><code>0x" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendHexValue ( SocketFD, + pPort, + Mtrr.Variables.Mtrr[ Count ].Base ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Mask + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "</td><td align=\"right\"><code>0x" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendHexValue ( SocketFD, + pPort, + Mtrr.Variables.Mtrr[ Count ].Mask ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Determine if the entry is valid + // + bValid = ( Mtrr.Variables.Mtrr[ Count ].Mask & VARIABLE_MTRR_VALID ) ? TRUE : FALSE; + + // + // Start + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "</code></td><td align=\"right\"><code>" ); + if ( EFI_ERROR ( Status )) { + break; + } + Addr = Mtrr.Variables.Mtrr[ Count ].Base & 0xfffffffffffff000ULL; + if ( bValid ) { + Status = HttpSendAnsiString ( SocketFD, + pPort, + "0x" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendHexValue ( SocketFD, + pPort, + Addr ); + } + else { + Status = HttpSendAnsiString ( SocketFD, + pPort, + "Invalid" ); + } + if ( EFI_ERROR ( Status )) { + break; + } + + // + // End + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "</code></td><td align=\"right\"><code>" ); + if ( EFI_ERROR ( Status )) { + break; + } + if ( bValid ) { + // + // Determine the end address + // + Mask = Mtrr.Variables.Mtrr[ Count ].Mask; + Value = Mask; + ShiftCount = 0; + while ( 0 < Value ) { + Value <<= 1; + ShiftCount += 1; + } + Value = 1; + Value <<= 64 - ShiftCount; + Value -= 1; + Value = ~Value; + Value |= Mask; + Value &= ~VARIABLE_MTRR_VALID; + Value = ~Value; + + Status = HttpSendAnsiString ( SocketFD, + pPort, + "0x" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendHexValue ( SocketFD, + pPort, + Addr + Value ); + } + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Type + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "</code></td><td>" ); + if ( EFI_ERROR ( Status )) { + break; + } + if ( bValid ) { + Type = Mtrr.Variables.Mtrr[ Count ].Base & 0xFF; + Status = HttpSendAnsiString ( SocketFD, + pPort, + ( DIM ( mMemoryType ) > Type ) + ? mMemoryType [ Type ] + : "Reserved" ); + } + if ( EFI_ERROR ( Status )) { + break; + } + + // + // End of row + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "</td></tr>\r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + } + if ( EFI_ERROR ( Status )) { + break; + } + + // + // End of table + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "</table>\r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + } + } + } + + // + // Send the page trailer + // + Status = HttpPageTrailer ( SocketFD, pPort, pbDone ); + break; + } + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} |