Esempio n. 1
0
/**
  Callback function executed when the EndOfDxe event group is signaled.

  We delay allocating StartupVector and saving the MTRR settings until BDS signals EndOfDxe.

  @param[in]  Event    Event whose notification function is being invoked.
  @param[out] Context  Pointer to the MTRR_SETTINGS buffer to fill in.
**/
VOID
EFIAPI
CpuS3DataOnEndOfDxe (
  IN  EFI_EVENT  Event,
  OUT VOID       *Context
  )
{
  EFI_STATUS         Status;
  ACPI_CPU_DATA_EX   *AcpiCpuDataEx;

  AcpiCpuDataEx = (ACPI_CPU_DATA_EX *) Context;
  //
  // Allocate a 4KB reserved page below 1MB
  //
  AcpiCpuDataEx->AcpiCpuData.StartupVector = BASE_1MB - 1;
  Status = gBS->AllocatePages (
                  AllocateMaxAddress,
                  EfiReservedMemoryType,
                  1,
                  &AcpiCpuDataEx->AcpiCpuData.StartupVector
                  );
  ASSERT_EFI_ERROR (Status);

  DEBUG ((EFI_D_VERBOSE, "%a\n", __FUNCTION__));
  MtrrGetAllMtrrs (&AcpiCpuDataEx->MtrrTable);

  //
  // Close event, so it will not be invoked again.
  //
  gBS->CloseEvent (Event);
}
Esempio n. 2
0
/**
  Triggers CPU-only reset and restores processor environment.

  This function triggers CPU-only reset and restores processor environment.

**/
VOID
CpuOnlyResetAndRestore (
  VOID
  )
{
  MTRR_SETTINGS  MtrrSetting;

  MtrrGetAllMtrrs (&MtrrSetting);

  InitiateCpuOnlyReset ();

  DispatchAPAndWait (
    TRUE,
    0,
    EarlyMpInit
    );

  EarlyMpInit (mCpuConfigConextBuffer.BspNumber);

  ProgramVirtualWireMode ();
}
Esempio n. 3
0
/**
  This function will be called when MRC is done.

  @param  PeiServices General purpose services available to every PEIM.

  @param  NotifyDescriptor Information about the notify event..

  @param  Ppi The notify context.

  @retval EFI_SUCCESS If the function completed successfully.
**/
EFI_STATUS
EFIAPI
MemoryDiscoveredPpiNotifyCallback (
  IN EFI_PEI_SERVICES           **PeiServices,
  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
  IN VOID                       *Ppi
  )
{
  EFI_STATUS                            Status;
  EFI_BOOT_MODE                         BootMode;
  UINT64                                MemoryLength;
  EFI_SMRAM_DESCRIPTOR                  *SmramDescriptor;
  UINTN                                 NumSmramRegions;
  UINT32                                RmuMainBaseAddress;
  UINT32                                RegData32;
  UINT8                                 CpuAddressWidth;
  UINT32                                RegEax;
  MTRR_SETTINGS                         MtrrSettings;
  EFI_PEI_READ_ONLY_VARIABLE2_PPI       *VariableServices;
  UINT8                                 MorControl;
  UINTN                                 DataSize;

  DEBUG ((EFI_D_INFO, "Platform PEIM Memory Callback\n"));

  NumSmramRegions = 0;
  SmramDescriptor = NULL;
  RmuMainBaseAddress = 0;

  PERF_START (NULL, "SetCache", NULL, 0);

  InfoPostInstallMemory (&RmuMainBaseAddress, &SmramDescriptor, &NumSmramRegions);
  ASSERT (SmramDescriptor != NULL);
  ASSERT (RmuMainBaseAddress != 0);

  MemoryLength = ((UINT64) RmuMainBaseAddress) + 0x10000;

  Status = PeiServicesGetBootMode (&BootMode);
  ASSERT_EFI_ERROR (Status);

  //
  // Get current MTRR settings
  //
  MtrrGetAllMtrrs (&MtrrSettings);

  //
  // Set all DRAM cachability to CacheWriteBack
  //
  Status = MtrrSetMemoryAttributeInMtrrSettings (&MtrrSettings, 0, MemoryLength, CacheWriteBack);
  ASSERT_EFI_ERROR (Status);

  //
  // RTC:28208 - System hang/crash when entering probe mode(ITP) when relocating SMBASE
  //             Workaround to make default SMRAM UnCachable
  //
  Status = MtrrSetMemoryAttributeInMtrrSettings (&MtrrSettings, 0x30000, SIZE_64KB, CacheUncacheable);
  ASSERT_EFI_ERROR (Status);

  //
  // Set new MTRR settings
  //
  MtrrSetAllMtrrs (&MtrrSettings);

  PERF_END (NULL, "SetCache", NULL, 0);

  //
  // Get necessary PPI
  //
  Status = PeiServicesLocatePpi (
             &gEfiPeiReadOnlyVariable2PpiGuid,           // GUID
             0,                                          // INSTANCE
             NULL,                                       // EFI_PEI_PPI_DESCRIPTOR
             (VOID **)&VariableServices                  // PPI
             );
  ASSERT_EFI_ERROR (Status);

  //
  // Detect MOR request by the OS.
  //
  MorControl = 0;
  DataSize = sizeof (MorControl);
  Status = VariableServices->GetVariable (
                               VariableServices,
                               MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
                               &gEfiMemoryOverwriteControlDataGuid,
                               NULL,
                               &DataSize,
                               &MorControl
                               );
  //
  // If OS requested a memory overwrite perform it now for Embedded SRAM
  //
  if (MOR_CLEAR_MEMORY_VALUE (MorControl)) {
    DEBUG ((EFI_D_INFO, "Clear Embedded SRAM per MOR request.\n"));
    if (PcdGet32 (PcdESramMemorySize) > 0) {
      if (PcdGet32 (PcdEsramStage1Base) == 0) {
        //
        // ZeroMem() generates an ASSERT() if Buffer parameter is NULL.
        // Clear byte at 0 and start clear operation at address 1.
        //
        *(UINT8 *)(0) = 0;
        ZeroMem ((VOID *)1, (UINTN)PcdGet32 (PcdESramMemorySize) - 1);
      } else {
        ZeroMem (
          (VOID *)(UINTN)PcdGet32 (PcdEsramStage1Base),
          (UINTN)PcdGet32 (PcdESramMemorySize)
          );
      }
    }
  }

  //
  // Install PeiReset for PeiResetSystem service
  //
  Status = PeiServicesInstallPpi (&mPpiList[0]);
  ASSERT_EFI_ERROR (Status);

  //
  // Do QNC initialization after MRC
  //
  PeiQNCPostMemInit ();

  Status = PeiServicesInstallPpi (&mPpiStall[0]);
  ASSERT_EFI_ERROR (Status);

  //
  // Set E000/F000 Routing
  //
  RegData32 = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
  RegData32 |= (BIT2|BIT1);
  QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, RegData32);

  if (BootMode == BOOT_IN_RECOVERY_MODE) {
    // Do nothing here. A generic RecoveryModule will handle it.
  } else if (BootMode == BOOT_ON_S3_RESUME) {
    return EFI_SUCCESS;
  } else {
    PeiServicesInstallFvInfoPpi (
      NULL,
      (VOID *) (UINTN) PcdGet32 (PcdFlashFvMainBase),
      PcdGet32 (PcdFlashFvMainSize),
      NULL,
      NULL
      );

    //
    // Publish the FVMAIN FV so the DXE Phase can dispatch drivers from this FV
    // and produce Load File Protocols for UEFI Applications in this FV.
    //
    BuildFvHob (
      PcdGet32 (PcdFlashFvMainBase),
      PcdGet32 (PcdFlashFvMainSize)
      );

    //
    // Publish the Payload FV so the DXE Phase can dispatch drivers from this FV
    // and produce Load File Protocols for UEFI Applications in this FV.
    //
    BuildFvHob (
      PcdGet32 (PcdFlashFvPayloadBase),
      PcdGet32 (PcdFlashFvPayloadSize)
      );
  }

  //
  // Build flash HOB, it's going to be used by GCD and E820 building
  // Map full SPI flash decode range (regardless of smaller SPI flash parts installed)
  //
  BuildResourceDescriptorHob (
    EFI_RESOURCE_FIRMWARE_DEVICE,
    (EFI_RESOURCE_ATTRIBUTE_PRESENT    |
    EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
    EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE),
    (SIZE_4GB - SIZE_8MB),
    SIZE_8MB
    );

  //
  // Create a CPU hand-off information
  //
  CpuAddressWidth = 32;
  AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
  if (RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) {
    AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &RegEax, NULL, NULL, NULL);
    CpuAddressWidth = (UINT8) (RegEax & 0xFF);
  }
  DEBUG ((EFI_D_INFO, "CpuAddressWidth: %d\n", CpuAddressWidth));

  BuildCpuHob (CpuAddressWidth, 16);

  ASSERT_EFI_ERROR (Status);

  return Status;
}
Esempio n. 4
0
/**
  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;
  }
Esempio n. 5
0
/**
  SMI handler for AP.

  @param     CpuIndex         AP processor Index.
  @param     ValidSmi         Indicates that current SMI is a valid SMI or not.
  @param     SyncMode         SMM MP sync mode.

**/
VOID
APHandler (
  IN      UINTN                     CpuIndex,
  IN      BOOLEAN                   ValidSmi,
  IN      SMM_CPU_SYNC_MODE         SyncMode
  )
{
  UINT64                            Timer;
  UINTN                             BspIndex;
  MTRR_SETTINGS                     Mtrrs;

  //
  // Timeout BSP
  //
  for (Timer = StartSyncTimer ();
       !IsSyncTimerTimeout (Timer) &&
       !mSmmMpSyncData->InsideSmm;
       ) {
    CpuPause ();
  }

  if (!mSmmMpSyncData->InsideSmm) {
    //
    // BSP timeout in the first round
    //
    if (mSmmMpSyncData->BspIndex != -1) {
      //
      // BSP Index is known
      //
      BspIndex = mSmmMpSyncData->BspIndex;
      ASSERT (CpuIndex != BspIndex);

      //
      // Send SMI IPI to bring BSP in
      //
      SendSmiIpi ((UINT32)gSmmCpuPrivate->ProcessorInfo[BspIndex].ProcessorId);

      //
      // Now clock BSP for the 2nd time
      //
      for (Timer = StartSyncTimer ();
           !IsSyncTimerTimeout (Timer) &&
           !mSmmMpSyncData->InsideSmm;
           ) {
        CpuPause ();
      }

      if (!mSmmMpSyncData->InsideSmm) {
        //
        // Give up since BSP is unable to enter SMM
        // and signal the completion of this AP
        WaitForSemaphore (&mSmmMpSyncData->Counter);
        return;
      }
    } else {
      //
      // Don't know BSP index. Give up without sending IPI to BSP.
      //
      WaitForSemaphore (&mSmmMpSyncData->Counter);
      return;
    }
  }

  //
  // BSP is available
  //
  BspIndex = mSmmMpSyncData->BspIndex;
  ASSERT (CpuIndex != BspIndex);

  //
  // Mark this processor's presence
  //
  mSmmMpSyncData->CpuData[CpuIndex].Present = TRUE;

  if (SyncMode == SmmCpuSyncModeTradition || SmmCpuFeaturesNeedConfigureMtrrs()) {
    //
    // Notify BSP of arrival at this point
    //
    ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);
  }

  if (SmmCpuFeaturesNeedConfigureMtrrs()) {
    //
    // Wait for the signal from BSP to backup MTRRs
    //
    WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);

    //
    // Backup OS MTRRs
    //
    MtrrGetAllMtrrs(&Mtrrs);

    //
    // Signal BSP the completion of this AP
    //
    ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);

    //
    // Wait for BSP's signal to program MTRRs
    //
    WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);

    //
    // Replace OS MTRRs with SMI MTRRs
    //
    ReplaceOSMtrrs (CpuIndex);

    //
    // Signal BSP the completion of this AP
    //
    ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);
  }

  while (TRUE) {
    //
    // Wait for something to happen
    //
    WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);

    //
    // Check if BSP wants to exit SMM
    //
    if (!mSmmMpSyncData->InsideSmm) {
      break;
    }

    //
    // BUSY should be acquired by SmmStartupThisAp()
    //
    ASSERT (
      !AcquireSpinLockOrFail (&mSmmMpSyncData->CpuData[CpuIndex].Busy)
      );

    //
    // Invoke the scheduled procedure
    //
    (*mSmmMpSyncData->CpuData[CpuIndex].Procedure) (
      (VOID*)mSmmMpSyncData->CpuData[CpuIndex].Parameter
      );

    //
    // Release BUSY
    //
    ReleaseSpinLock (&mSmmMpSyncData->CpuData[CpuIndex].Busy);
  }

  if (SmmCpuFeaturesNeedConfigureMtrrs()) {
    //
    // Notify BSP the readiness of this AP to program MTRRs
    //
    ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);

    //
    // Wait for the signal from BSP to program MTRRs
    //
    WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);

    //
    // Restore OS MTRRs
    //
    SmmCpuFeaturesReenableSmrr ();
    MtrrSetAllMtrrs(&Mtrrs);
  }

  //
  // Notify BSP the readiness of this AP to Reset states/semaphore for this processor
  //
  ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);

  //
  // Wait for the signal from BSP to Reset states/semaphore for this processor
  //
  WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);

  //
  // Reset states/semaphore for this processor
  //
  mSmmMpSyncData->CpuData[CpuIndex].Present = FALSE;

  //
  // Notify BSP the readiness of this AP to exit SMM
  //
  ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);

}
Esempio n. 6
0
/**
  SMI handler for BSP.

  @param     CpuIndex         BSP processor Index
  @param     SyncMode         SMM MP sync mode

**/
VOID
BSPHandler (
  IN      UINTN                     CpuIndex,
  IN      SMM_CPU_SYNC_MODE         SyncMode
  )
{
  UINTN                             Index;
  MTRR_SETTINGS                     Mtrrs;
  UINTN                             ApCount;
  BOOLEAN                           ClearTopLevelSmiResult;
  UINTN                             PresentCount;

  ASSERT (CpuIndex == mSmmMpSyncData->BspIndex);
  ApCount = 0;

  //
  // Flag BSP's presence
  //
  mSmmMpSyncData->InsideSmm = TRUE;

  //
  // Initialize Debug Agent to start source level debug in BSP handler
  //
  InitializeDebugAgent (DEBUG_AGENT_INIT_ENTER_SMI, NULL, NULL);

  //
  // Mark this processor's presence
  //
  mSmmMpSyncData->CpuData[CpuIndex].Present = TRUE;

  //
  // Clear platform top level SMI status bit before calling SMI handlers. If
  // we cleared it after SMI handlers are run, we would miss the SMI that
  // occurs after SMI handlers are done and before SMI status bit is cleared.
  //
  ClearTopLevelSmiResult = ClearTopLevelSmiStatus();
  ASSERT (ClearTopLevelSmiResult == TRUE);

  //
  // Set running processor index
  //
  gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu = CpuIndex;

  //
  // If Traditional Sync Mode or need to configure MTRRs: gather all available APs.
  //
  if (SyncMode == SmmCpuSyncModeTradition || SmmCpuFeaturesNeedConfigureMtrrs()) {

    //
    // Wait for APs to arrive
    //
    SmmWaitForApArrival();

    //
    // Lock the counter down and retrieve the number of APs
    //
    mSmmMpSyncData->AllCpusInSync = TRUE;
    ApCount = LockdownSemaphore (&mSmmMpSyncData->Counter) - 1;

    //
    // Wait for all APs to get ready for programming MTRRs
    //
    WaitForAllAPs (ApCount);

    if (SmmCpuFeaturesNeedConfigureMtrrs()) {
      //
      // Signal all APs it's time for backup MTRRs
      //
      ReleaseAllAPs ();

      //
      // WaitForSemaphore() may wait for ever if an AP happens to enter SMM at
      // exactly this point. Please make sure PcdCpuSmmMaxSyncLoops has been set
      // to a large enough value to avoid this situation.
      // Note: For HT capable CPUs, threads within a core share the same set of MTRRs.
      // We do the backup first and then set MTRR to avoid race condition for threads
      // in the same core.
      //
      MtrrGetAllMtrrs(&Mtrrs);

      //
      // Wait for all APs to complete their MTRR saving
      //
      WaitForAllAPs (ApCount);

      //
      // Let all processors program SMM MTRRs together
      //
      ReleaseAllAPs ();

      //
      // WaitForSemaphore() may wait for ever if an AP happens to enter SMM at
      // exactly this point. Please make sure PcdCpuSmmMaxSyncLoops has been set
      // to a large enough value to avoid this situation.
      //
      ReplaceOSMtrrs (CpuIndex);

      //
      // Wait for all APs to complete their MTRR programming
      //
      WaitForAllAPs (ApCount);
    }
  }

  //
  // The BUSY lock is initialized to Acquired state
  //
  AcquireSpinLockOrFail (&mSmmMpSyncData->CpuData[CpuIndex].Busy);

  //
  // Restore SMM Configuration in S3 boot path.
  //
  if (mRestoreSmmConfigurationInS3) {
    //
    // Configure SMM Code Access Check feature if available.
    //
    ConfigSmmCodeAccessCheck ();
    mRestoreSmmConfigurationInS3 = FALSE;
  }

  //
  // Invoke SMM Foundation EntryPoint with the processor information context.
  //
  gSmmCpuPrivate->SmmCoreEntry (&gSmmCpuPrivate->SmmCoreEntryContext);

  //
  // Make sure all APs have completed their pending none-block tasks
  //
  for (Index = mMaxNumberOfCpus; Index-- > 0;) {
    if (Index != CpuIndex && mSmmMpSyncData->CpuData[Index].Present) {
      AcquireSpinLock (&mSmmMpSyncData->CpuData[Index].Busy);
      ReleaseSpinLock (&mSmmMpSyncData->CpuData[Index].Busy);;
    }
  }

  //
  // Perform the remaining tasks
  //
  PerformRemainingTasks ();

  //
  // If Relaxed-AP Sync Mode: gather all available APs after BSP SMM handlers are done, and
  // make those APs to exit SMI synchronously. APs which arrive later will be excluded and
  // will run through freely.
  //
  if (SyncMode != SmmCpuSyncModeTradition && !SmmCpuFeaturesNeedConfigureMtrrs()) {

    //
    // Lock the counter down and retrieve the number of APs
    //
    mSmmMpSyncData->AllCpusInSync = TRUE;
    ApCount = LockdownSemaphore (&mSmmMpSyncData->Counter) - 1;
    //
    // Make sure all APs have their Present flag set
    //
    while (TRUE) {
      PresentCount = 0;
      for (Index = mMaxNumberOfCpus; Index-- > 0;) {
        if (mSmmMpSyncData->CpuData[Index].Present) {
          PresentCount ++;
        }
      }
      if (PresentCount > ApCount) {
        break;
      }
    }
  }

  //
  // Notify all APs to exit
  //
  mSmmMpSyncData->InsideSmm = FALSE;
  ReleaseAllAPs ();

  //
  // Wait for all APs to complete their pending tasks
  //
  WaitForAllAPs (ApCount);

  if (SmmCpuFeaturesNeedConfigureMtrrs()) {
    //
    // Signal APs to restore MTRRs
    //
    ReleaseAllAPs ();

    //
    // Restore OS MTRRs
    //
    SmmCpuFeaturesReenableSmrr ();
    MtrrSetAllMtrrs(&Mtrrs);

    //
    // Wait for all APs to complete MTRR programming
    //
    WaitForAllAPs (ApCount);
  }

  //
  // Stop source level debug in BSP handler, the code below will not be
  // debugged.
  //
  InitializeDebugAgent (DEBUG_AGENT_INIT_EXIT_SMI, NULL, NULL);

  //
  // Signal APs to Reset states/semaphore for this processor
  //
  ReleaseAllAPs ();

  //
  // Perform pending operations for hot-plug
  //
  SmmCpuUpdate ();

  //
  // Clear the Present flag of BSP
  //
  mSmmMpSyncData->CpuData[CpuIndex].Present = FALSE;

  //
  // Gather APs to exit SMM synchronously. Note the Present flag is cleared by now but
  // WaitForAllAps does not depend on the Present flag.
  //
  WaitForAllAPs (ApCount);

  //
  // Reset BspIndex to -1, meaning BSP has not been elected.
  //
  if (FeaturePcdGet (PcdCpuSmmEnableBspElection)) {
    mSmmMpSyncData->BspIndex = (UINT32)-1;
  }

  //
  // Allow APs to check in from this point on
  //
  mSmmMpSyncData->Counter = 0;
  mSmmMpSyncData->AllCpusInSync = FALSE;
}