C++程序  |  826行  |  22.69 KB

/**
  @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;
}