/** 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; MSR_IA32_MTRRCAP_REGISTER Capabilities; UINTN Count; MSR_IA32_MTRR_DEF_TYPE_REGISTER DefType; UINTN Index; UINT64 Mask; 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.Uint64 = AsmReadMsr64 ( MSR_IA32_MTRRCAP ); DefType.Uint64 = AsmReadMsr64 ( MSR_IA32_MTRR_DEF_TYPE ); // // Display the capabilities // Status = HttpSendAnsiString ( SocketFD, pPort, "<p>Capabilities: " ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendHexValue ( SocketFD, pPort, Capabilities.Uint64 ); 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.Uint64); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, ", MTRRs " ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, ( 0 != DefType.Bits.E ) ? "Enabled" : "Disabled" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, ", Fixed MTRRs " ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, ( 0 != DefType.Bits.FE ) ? "Enabled" : "Disabled" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } Type = DefType.Uint64 & 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.Bits.E ) { 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.Bits.FIX ) && ( 0 != DefType.Bits.FE)) { // // 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 // if ( 0 < Capabilities.Bits.VCNT ) { // // 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; Capabilities.Bits.VCNT > 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; }
/** Page to display the memory map @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 MemoryMapPage ( IN int SocketFD, IN WSDT_PORT * pPort, OUT BOOLEAN * pbDone ) { UINT64 Attributes; BOOLEAN bSomethingDisplayed; UINTN Count; EFI_GCD_MEMORY_SPACE_DESCRIPTOR * pMemoryEnd; EFI_GCD_MEMORY_SPACE_DESCRIPTOR * pMemoryDescriptor; EFI_GCD_MEMORY_SPACE_DESCRIPTOR * pMemoryDescriptorStart; EFI_STATUS Status; DBG_ENTER ( ); // // Send the memory map page // pMemoryDescriptorStart = NULL; for ( ; ; ) { // // Send the page header // Status = HttpPageHeader ( SocketFD, pPort, L"Memory Map" ); if ( EFI_ERROR ( Status )) { break; } // // Start the table // Status = HttpSendAnsiString ( SocketFD, pPort, "<h1>Memory Map</h1>\r\n" "<table>\r\n" " <tr><th align=\"right\">Type</th><th align=\"right\">Start</th><th align=\"right\">End</th><th align=\"right\">Attributes</th></tr>\r\n" ); if ( EFI_ERROR ( Status )) { break; } // // Get the memory map // Status = gDS->GetMemorySpaceMap ( &Count, &pMemoryDescriptor ); if ( !EFI_ERROR ( Status )) { pMemoryDescriptorStart = pMemoryDescriptor; pMemoryEnd = &pMemoryDescriptor[ Count ]; while ( pMemoryEnd > pMemoryDescriptor ) { // // Display the type // Status = HttpSendAnsiString ( SocketFD, pPort, "<tr><td align=\"right\"><code>" ); if ( EFI_ERROR ( Status )) { break; } if ( DIM ( mpMemoryType ) > pMemoryDescriptor->GcdMemoryType ) { Status = HttpSendAnsiString ( SocketFD, pPort, mpMemoryType[ pMemoryDescriptor->GcdMemoryType ]); } else { Status = HttpSendValue ( SocketFD, pPort, pMemoryDescriptor->GcdMemoryType ); } if ( EFI_ERROR ( Status )) { break; } // // Display the start address // Status = HttpSendAnsiString ( SocketFD, pPort, "</code></td><td align=\"right\"><code>0x" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendHexValue ( SocketFD, pPort, pMemoryDescriptor->BaseAddress ); if ( EFI_ERROR ( Status )) { break; } // // Display the end address // Status = HttpSendAnsiString ( SocketFD, pPort, "</code></td><td align=\"right\"><code>0x" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendHexValue ( SocketFD, pPort, pMemoryDescriptor->BaseAddress + pMemoryDescriptor->Length - 1 ); if ( EFI_ERROR ( Status )) { break; } // // Display the attributes // Status = HttpSendAnsiString ( SocketFD, pPort, "</code></td><td align=\"right\"><code>0x" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendHexValue ( SocketFD, pPort, pMemoryDescriptor->Attributes ); if ( EFI_ERROR ( Status )) { break; } // // Decode the attributes // Status = HttpSendAnsiString ( SocketFD, pPort, "</code></td><td>" ); if ( EFI_ERROR ( Status )) { break; } bSomethingDisplayed = FALSE; Attributes = pMemoryDescriptor->Attributes; if ( 0 != ( Attributes & EFI_MEMORY_RUNTIME )) { bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "Runtime" ); if ( EFI_ERROR ( Status )) { break; } } if ( 0 != ( Attributes & EFI_MEMORY_XP )) { if ( bSomethingDisplayed ) { Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } } bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "No Execute" ); if ( EFI_ERROR ( Status )) { break; } } if ( 0 != ( Attributes & EFI_MEMORY_RP )) { if ( bSomethingDisplayed ) { Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } } bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "No Read" ); if ( EFI_ERROR ( Status )) { break; } } if ( 0 != ( Attributes & EFI_MEMORY_WP )) { if ( bSomethingDisplayed ) { Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } } bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "No Write" ); if ( EFI_ERROR ( Status )) { break; } } if ( 0 != ( Attributes & EFI_MEMORY_UCE )) { if ( bSomethingDisplayed ) { Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } } bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "UCE" ); if ( EFI_ERROR ( Status )) { break; } } if ( 0 != ( Attributes & EFI_MEMORY_WB )) { if ( bSomethingDisplayed ) { Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } } bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "Write Back" ); if ( EFI_ERROR ( Status )) { break; } } if ( 0 != ( Attributes & EFI_MEMORY_WT )) { if ( bSomethingDisplayed ) { Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } } bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "Write Through" ); if ( EFI_ERROR ( Status )) { break; } } if ( 0 != ( Attributes & EFI_MEMORY_WC )) { if ( bSomethingDisplayed ) { Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } } bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "Write Combining" ); if ( EFI_ERROR ( Status )) { break; } } if ( 0 != ( Attributes & EFI_MEMORY_UC )) { if ( bSomethingDisplayed ) { Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } } bSomethingDisplayed = TRUE; Status = HttpSendAnsiString ( SocketFD, pPort, "Uncached" ); if ( EFI_ERROR ( Status )) { break; } } // // Finish the row // Status = HttpSendAnsiString ( SocketFD, pPort, "</td></tr>" ); if ( EFI_ERROR ( Status )) { break; } // // Set the next memory descriptor // pMemoryDescriptor += 1; } } // // Finish the table // Status = HttpSendAnsiString ( SocketFD, pPort, "</table>\r\n" ); if ( EFI_ERROR ( Status )) { break; } // // Send the page trailer // Status = HttpPageTrailer ( SocketFD, pPort, pbDone ); break; } // // Release the memory descriptors // if ( NULL != pMemoryDescriptorStart ) { FreePool ( pMemoryDescriptorStart ); } // // Return the operation status // DBG_EXIT_STATUS ( Status ); return Status; }