示例#1
0
EFI_STATUS
EFIAPI
AmdRasSmmDxeDriverEntryPoint (
  IN       EFI_HANDLE        ImageHandle,
  IN       EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS                      Status;
  BOOLEAN                         InSmm;
  EFI_HANDLE                      hNrthBrdgError = NULL;
  EFI_SMM_BASE_PROTOCOL           *SmmBase = NULL;
  EFI_LOADED_IMAGE_PROTOCOL       *LoadedImage = NULL;
  EFI_DEVICE_PATH_PROTOCOL        *ImageDevicePath = NULL;
  EFI_DEVICE_PATH_PROTOCOL        *NewFilePath = NULL;
  AMD_RAS_DXE_INTERFACE_PROTOCOL  *RasIntProtocol = NULL;
  SMM_SETUP_CONFIG                SmmSetupCfg;


  // Initialize Global Variables
  Status = InitializeRasRuntime (
                                 ImageHandle,          // IN EFI_HANDLE
                                 SystemTable           // IN EFI_SYSTEM_TABLE
                                 );
  if (EFI_ERROR (Status)) {
    ASSERT_EFI_ERROR (Status);
    return Status;          // Error detected while trying to locate SMM Base Protocol
  }

  // Locate SMM Base Protocol
  Status  = gBS->LocateProtocol (
                                 &gEfiSmmBaseProtocolGuid, // IN EFI_GUID Published unique identifier of requested protocol GUID to locate
                                 NULL,                     // IN VOID* Published unique identifier of requested protocol GUID
                                 &SmmBase                  // OUT VOID** Returns address of pointer for SMM Base protocol interface
                                 );
  if (EFI_ERROR (Status)) {
    ASSERT_EFI_ERROR (Status);
    return Status;          // Error detected while trying to locate SMM Base Protocol
  }

  // Save the SMM Base system table pointer
  SmmBase->GetSmstLocation (SmmBase, &gSmst);

  // Determine if we are in SMM or not
  SmmBase->InSmm (SmmBase, &InSmm);

  if (!InSmm) {
    //
    // Not in SMM so load this driver's SMM image to memory
    //
    // Configure Northbridge Interrupt Event to make an I/O Write to SMI Command Port in the
    // Southbridge and cause a Software SMI for which we will handle in the NbSmiHandler
    // SMI service routine.
    Status = ConfigNbSmiProcessing ();

    // Query image handle to see if it supports a requested protocol and then get an address of the protocol image to be loaded
    Status = gBS->HandleProtocol (
                                  ImageHandle,                   // Handle of requested protocol
                                  &gEfiLoadedImageProtocolGuid,  // Published unique identifier of requested protocol GUID
                                  (VOID*)&LoadedImage            // Returns address of pointer for requested protocol interface of the image
                                  );
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return Status;            // Error detected while trying to query LoadImage protocol
    }

    // Query device handle of loaded image to see if it supports a requested protocol and then get an address of the prototocl device path
    Status = gBS->HandleProtocol (
                                  LoadedImage->DeviceHandle,   // Handle of requested protocol
                                  &gEfiDevicePathProtocolGuid, // Published unique identifier of requested protocol GUID
                                  (VOID*)&ImageDevicePath      // Returns address of pointer for requested protocol interface
                                  );
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return Status;
    }

    // Add this image's device path to the loaded image device path image and return
    // a pointer to the new file path.
    NewFilePath = AddDevicePath (
                                 ImageDevicePath,      // IN EFI_DEVICE_PATH_PROTOCOL
                                 LoadedImage->FilePath // IN EFI_DEVICE_PATH_PROTOCOL Device Path Image to add
                                 );

    //Load the image in System Management RAM; it will automatically generate SMI.
    Status = SmmBase->Register (
                                SmmBase,         // IN *This Addreess of pointer for SMM Base protocol interface)
                                NewFilePath,     // IN EFI_DEVICE_PATH_PROTOCOL
                                NULL,            // IN SourceBuffer OPTIONAL
                                0,               // IN SourceSize OPTIONAL
                                &hNrthBrdgError, // OUT *ImageHandle
                                FALSE            // IN LegacyIA32Binary OPTIONAL
                                );

    // Free up residual heap memory if not equal to NULL
    if (NewFilePath) {
         gBS->FreePool (NewFilePath);
    }
  } else {
    // We are in SMM

    //
    // Callout to use platform-specific Setup
    //
    Status = AmdRasSmmCallout (ECC_HNDLR_CALLOUT_ID, &SmmSetupCfg);

    if (EFI_ERROR (Status)) {
      SmmSetupCfg.EccHandlerEnable = FALSE;   //Load default value = ECC Disabled
    }

    // Enable / Disable RAS MCA ECC Support
    if (SmmSetupCfg.EccHandlerEnable == TRUE) {
      // Callback to execute from within SMM, error occurs if called from Boot Services mode
      Status = SmmBase->RegisterCallback (
                                          SmmBase,        // IN *This
                                          ImageHandle,    // IN SmmImageHandle
                                          MC4SmmHandler,  // IN EFI SMM Dispatcher Callback Entry Point Address
                                          FALSE,          // IN Makelast (SMM Dispatcher should call this handler last) OPTIONAL
                                          FALSE           // IN FloatingPointSave OPTIONAL
                                          );
      if (EFI_ERROR (Status)) {
        ASSERT_EFI_ERROR (Status);
        return Status;
      }

      // Update Global Varibles for this driver
      Status = UpdateGlobalVars ();
      if (EFI_ERROR (Status)) {
        ASSERT_EFI_ERROR (Status);
        return Status;
      }
    }  //End-- Enable / Disable ECC Handler Support
  } // End-- if(!InSmm)

  if (!InSmm) {
    // Allocate memory for a new protocol structure
    Status = gBS->AllocatePool (
                                EfiBootServicesData,
                                sizeof (AMD_RAS_DXE_INTERFACE_PROTOCOL),
                                &RasIntProtocol
                                );

    if (RasIntProtocol == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }

    // Zero out memory buffer
    EfiCommonLibZeroMem (
                         RasIntProtocol,
                         sizeof (AMD_RAS_DXE_INTERFACE_PROTOCOL)
                         );

    // Locate AMD RAS Interface Protocol
    Status  = gBS->LocateProtocol (
                                   &gAmdRasDxeInterfaceProtocolGuid,  // IN EFI_GUID Published unique identifier of requested protocol GUID to locate
                                   NULL,                              // IN VOID* Published unique identifier of requested protocol GUID
                                   (VOID **)&RasIntProtocol           // OUT VOID** Returns address of pointer for SMM Base protocol interface
                                   );
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_SUCCESS;         // Error detected while trying to locate RAS Interface Protocol
    }

    // Callout to get ECC Threshold BIOS Setup option config.
    Status = AmdRasSmmCallout (ECC_THRESH_COUNTER_CALLOUT_ID, &SmmSetupCfg);

    if (EFI_ERROR (Status)) {
      gRasNbCorrMemConfig.ThreshLimit = 0xFFE;   // Load default value = threshold value of 1 (1's complement)
    } else {
      gRasNbCorrMemConfig.ThreshLimit = SmmSetupCfg.DramErrorThreshold;
    }

    // Callout to get RAS Handle Type BIOS Setup option config.
    Status = AmdRasSmmCallout (RAS_HANDLE_CALLOUT_ID, &SmmSetupCfg);

    if (EFI_ERROR (Status)) {
        gRasNbCorrMemConfig.DevCommon.ErrorMonitorType = APIC;    // Default to APIC interrupt = 1 on error
    } else {
      if (SmmSetupCfg.RasHandleType == 1) {
        gRasNbCorrMemConfig.DevCommon.ErrorMonitorType = APIC;    // APIC interrupt = 1
      }
    }

    // Configure Correctable Memory Error Operation
    Status = RasIntProtocol->AmdSetErrorConfigDevice (
                                                      RasIntProtocol,                          // IN *This
                                                      gRasNbCorrMemConfig.DevCommon.DeviceID,  // IN UINTN (enum AMD_RAS_DEVICE_ID)
                                                      (VOID*) &gRasNbCorrMemConfig             // IN OUT VOID* RAS Device Struct
                                                      );
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_SUCCESS;       // Error detected while trying to locate SMM Base Protocol
    }

    // Configure UnCorrectable Memory Error Operation
    Status = RasIntProtocol->AmdSetErrorConfigDevice (
                                                      RasIntProtocol,                            // IN *This
                                                      gRasNbUnCorrMemConfig.DevCommon.DeviceID,  // IN UINTN (enum AMD_RAS_DEVICE_ID)
                                                      (VOID*) &gRasNbUnCorrMemConfig             // IN OUT VOID* RAS Device Struct
                                                      );
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_SUCCESS;       // Error detected while trying to locate SMM Base Protocol
    }
  } // End-- if (!InSmm)

  return Status;
}
示例#2
0
文件: FchSmm.c 项目: fishbaoz/edk2ml
EFI_STATUS
FchSmmEntryPoint (
  IN       EFI_HANDLE         ImageHandle,
  IN       EFI_SYSTEM_TABLE   *SystemTable
  )

{
  FCH_INIT_PROTOCOL            *pFchCimxInitProtocol;
  EFI_STATUS                      Status;
  BOOLEAN                         InSmm;
  EFI_SMM_BASE_PROTOCOL           *SmmBase;
  EFI_LOADED_IMAGE_PROTOCOL       *LoadedImage;
  EFI_DEVICE_PATH_PROTOCOL        *ImageDevicePath;
  EFI_DEVICE_PATH_PROTOCOL        *CompleteFilePath;
  EFI_HANDLE                      SmmImageHandle;

  //
  // Initialize EFI library
  //
  InSmm    = FALSE;
  gST      = SystemTable;
  gBS      = SystemTable->BootServices;

  Status = gBS->LocateProtocol (
                  &gEfiSmmBaseProtocolGuid,
                  NULL,
                  &SmmBase
                  );

  if (EFI_ERROR (Status)) {
    return Status;
  }
  SmmBase->GetSmstLocation (
             SmmBase,
             &mSmst
             );
  SmmBase->InSmm (
             SmmBase,
             &InSmm
             );


  if (!InSmm) {
    //
    // Not in SMM. Load this driver's image into SMRAM
    //
    if (ImageHandle != NULL) {
      Status = gBS->HandleProtocol (
                      ImageHandle,
                      &gEfiLoadedImageProtocolGuid,
                      &LoadedImage
                      );
      if (EFI_ERROR (Status)) {
        return Status;
      }

      Status = gBS->HandleProtocol (
                      LoadedImage->DeviceHandle,
                      &gEfiDevicePathProtocolGuid,
                      (VOID*) &ImageDevicePath
                      );

      if (EFI_ERROR (Status)) {
        return Status;
      }

      CompleteFilePath = AppendDevicePath (
                           ImageDevicePath,
                           LoadedImage->FilePath
                           );

      // Load the image in memory to SMRAM, this automatically triggers SMI
      SmmBase->Register (
                 SmmBase,
                 CompleteFilePath,
                 NULL,
                 0,
                 &SmmImageHandle,
                 FALSE
                 );
    }
  } else {
    //
    // We're now in SMM!
    //

    //
    // Initialize global variables
    //
    Status = mSmst->SmmAllocatePool (
                      EfiRuntimeServicesData,
                      0x100,
                      &mFchPciIrqRoutingTable
                      );
    if (EFI_ERROR (Status)) {
      return Status;
    }

    Status = gBS->LocateProtocol (
                    &gFchInitProtocolGuid,
                    NULL,
                    &pFchCimxInitProtocol
                    );
    if (!EFI_ERROR (Status)) {
      EfiCopyMem (
        &gFchInitInSmm,
        pFchCimxInitProtocol,
        sizeof (FCH_INIT_PROTOCOL)
        );
    } else {
      return EFI_ABORTED;
    }

    Status = FchSmmRegistrationCenter ();
    return Status;
  }
  return Status;
}
示例#3
0
EFI_STATUS
EFIAPI
AmdRasApeiDxeDriverEntryPoint (
  IN   EFI_HANDLE        ImageHandle,
  IN   EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS                      Status = EFI_SUCCESS;
  EFI_HANDLE                      Handle = NULL;
  EFI_HANDLE                      hEinj = NULL;
  AMD_RAS_APEI_PROTOCOL           *AmdRasApeiProtocol;
  BOOLEAN                         InSmm;
  EFI_SMM_BASE_PROTOCOL           *SmmBase = NULL;
  EFI_DEVICE_PATH_PROTOCOL        *ImageDevicePath = NULL;
  EFI_DEVICE_PATH_PROTOCOL        *NewFilePath = NULL;
  EFI_LOADED_IMAGE_PROTOCOL       *LoadedImage = NULL;
  EFI_SMM_SW_DISPATCH_PROTOCOL    *SwDispatch = NULL;
  EFI_SMM_SW_DISPATCH_CONTEXT     SwContext;
  EFI_ACPI_SUPPORT_PROTOCOL       *AcpiSupportProtocol = NULL;
  EFI_HANDLE                      SwHandle = NULL;
  EFI_HANDLE                      hNewHandle = NULL;
  UINTN                           BufferSize;
  UINTN                           HestTblHandle;
  UINT64                          Address64;
  UINT32                          Value32;
  //
  // Initialize Local Variables
  //
  InSmm = FALSE;
  BufferSize = 0;
  HestTblHandle = 0;

  //
  // Initialize Global Variables
  //
  EfiInitializeApei (ImageHandle, SystemTable);

  // Locate SMM Base Protocol
  Status  = gBS->LocateProtocol (
                                 &gEfiSmmBaseProtocolGuid,  // IN EFI_GUID Published unique identifier of requested protocol GUID to locate
                                 NULL,                      // IN VOID* Published unique identifier of requested protocol GUID
                                 &SmmBase                   // OUT VOID** Returns address of pointer for SMM Base protocol interface
                                 );

  if (EFI_ERROR (Status)) {
    ASSERT_EFI_ERROR (Status);
    return Status;     // Error detected while trying to locate SMM Base Protocol
  }

  // Save the SMM Base system table pointer
  SmmBase->GetSmstLocation (SmmBase, &gSmst);

  // Determine if we are in SMM or not
  SmmBase->InSmm (SmmBase, &InSmm);

  if (!InSmm) {
    // Query image handle to see if it supports a requested protocol and then get an address of the protocol image to be loaded
    Status = gBS->HandleProtocol (
                                  ImageHandle,                  // Handle of requested protocol
                                  &gEfiLoadedImageProtocolGuid, // Published unique identifier of requested protocol GUID
                                  (VOID*)&LoadedImage           // Returns address of pointer for requested protocol interface of the image
                                  );
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return Status;            // Error detected while trying to query LoadImage protocol
    }

    // Query device handle of loaded image to see if it supports a requested protocol and then get an address of the prototocl device path
    Status = gBS->HandleProtocol (
                                  LoadedImage->DeviceHandle,   // Handle of requested protocol
                                  &gEfiDevicePathProtocolGuid, // Published unique identifier of requested protocol GUID
                                  (VOID*) &ImageDevicePath     // Returns address of pointer for requested protocol interface
                                  );
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return Status;
    }

    // Add this image's device path to the loaded image device path image and return
    // a pointer to the new file path.
    NewFilePath = AddDevicePath (
                                 ImageDevicePath,         // IN EFI_DEVICE_PATH_PROTOCOL*
                                 LoadedImage->FilePath    // IN EFI_DEVICE_PATH_PROTOCOL* Device Path Image to add
                                 );

    //Load the image in System Management RAM; it will automatically generate an SMI.
    Status = SmmBase->Register (
                                SmmBase,      // IN *This Addreess of pointer for SMM Base protocol interface)
                                NewFilePath,  // IN EFI_DEVICE_PATH_PROTOCOL
                                NULL,         // IN SourceBuffer OPTIONAL
                                0,            // IN SourceSize OPTIONAL
                                &hEinj,       // OUT *ImageHandle
                                FALSE         // IN LegacyIA32Binary OPTIONAL
                                );

    // Free up residual heap memory if not equal to NULL
    if (NewFilePath) {
      gBS->FreePool (NewFilePath);
    }

    if (EFI_ERROR (Status)) {
      switch (EFIERR (Status))
      {
      case EFI_LOAD_ERROR:
        break;
      case EFI_INVALID_PARAMETER:
        break;
      case EFI_UNSUPPORTED:
        break;
      default:
        ;
      }
      return Status;
    }
  } else {
    // We are in SMM...
    // Allocate Memory for type Runtime Services Data - APEI Module Private Data
    Status = gBS->AllocatePool (EfiRuntimeServicesData, sizeof (APEI_DRIVER_PRIVATE_DATA), &mApeiPrivData);
    if (EFI_ERROR (Status)) {
      return Status;
    }

    // Allocate Memory for type Runtime Services Data - APEI Interface
    Status = gBS->AllocatePool (EfiRuntimeServicesData, sizeof (AMD_APEI_INTERFACE), &mApeiInterface);
    if (EFI_ERROR (Status)) {
      return Status;
    }

    // Locate SW SMM Dispatch Protocol
    Status  = gBS->LocateProtocol (
                                   &gEfiSmmSwDispatchProtocolGuid, // IN EFI_GUID Published unique identifier of requested protocol GUID to locate
                                   NULL,                           // IN VOID* Published unique identifier of requested protocol GUID
                                   &SwDispatch                     // OUT VOID** Returns address of pointer for SMM Base protocol interface
                                   );
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return Status;
    }

    SwContext.SwSmiInputValue = EINJ_BEGIN_INJ_CMD;
    // Register EINJ SMM callback handler.
    Status = SwDispatch->Register (
                                   SwDispatch,           // IN *This
                                   ApeiEinjSwSmiHandler, // IN EFI SW SMM Dispatcher Callback Entry Point Address
                                   &SwContext,           // IN SwContext
                                   &SwHandle             // IN OUT SwHandle
                                   );
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return Status;
    }

    SwContext.SwSmiInputValue = ERST_EXECUTE_OPERATION_CMD;
    // Register ERST SMM callback handler.
    Status = SwDispatch->Register (
                                   SwDispatch,
                                   ApeiErstSwSmiHandler,
                                   &SwContext,
                                   &SwHandle
                                   );
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return Status;
    }

    // Allocate Memory for the the AMD_RAS_APEI_PROTOCOL protocol.
    Status = gBS->AllocatePool (
                                EfiBootServicesData,              // IN EFI_MEMORY_TYPE PoolType
                                sizeof (AMD_RAS_APEI_PROTOCOL),   // IN UINTN Size
                                &AmdRasApeiProtocol               // OUT VOID **Buffer
                                );
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_OUT_OF_RESOURCES;    // Error detected while trying to locate SMM Base Protocol
    }

    EfiCommonLibZeroMem (AmdRasApeiProtocol, sizeof (AMD_RAS_APEI_PROTOCOL));

    // Initialize BERT
    ApeiBertInit ();
    // Initialize HEST
    ApeiHestInit ();
    // Determine if we have ECC error enable bits set
    Address64 = mCfgMmioBase | ((0x18 << 15) | (3 << 12) | 0x44); //F3:44 MC4_NB_CFG
    Value32 = RasSmmReadMem32 (Address64);
    if (Value32 & (1 << 22)) {
      //Initialize EINJ if ECC is Enabled
      ApeiEinjInit ();
    }
    // Initialize ERST
    ApeiErstInit ();

    AmdRasApeiProtocol->AmdApeiInterface = mApeiInterface;
    mApeiInterface->ApeiPrivData = mApeiPrivData;

    AmdRasApeiProtocol->AddBootErrorRecordEntry = 0;
    AmdRasApeiProtocol->AddHestErrorSourceEntry = 0;

    Status = gBS->InstallProtocolInterface (
                                            &Handle,                  // IN OUT EFI_HANDLE
                                            &gAmdRasApeiProtocolGuid, // IN EFI_GUID
                                            EFI_NATIVE_INTERFACE,     // IN EFI_INITERFACE_TYPE
                                            AmdRasApeiProtocol        // IN VOID* Interface
                                            );
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_PROTOCOL_ERROR;    // Error detected while trying to locate SMM Base Protocol
    }
  } // End-- if(!InSmm)

  //
  // Do more non-SMM configuration
  //
  if (!InSmm) {
    Status = gBS->LocateProtocol (
                                  &gAmdRasApeiProtocolGuid,
                                  NULL,
                                  &AmdRasApeiProtocol
                                  );

    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_PROTOCOL_ERROR;   // Error detected while trying to locate SMM Base Protocol
    }

    mApeiInterface = AmdRasApeiProtocol->AmdApeiInterface;
    mApeiPrivData = mApeiInterface->ApeiPrivData;

    // Initialize function pointers to protocol interfaces
    AmdRasApeiProtocol->AddBootErrorRecordEntry = &AddBertErrorRecord;
    AmdRasApeiProtocol->AddHestErrorSourceEntry = &AddHestErrorRecord;

    //
    //  Find the protocol that was installed during SMM phase and reinstall it during
    //  Non-SMM phase as well.
    //

    // Get the buffer size for the EFI_HANDLE
    BufferSize = sizeof (EFI_HANDLE);

    // Returns an array of handles that support a specified protocol.
    Status = gBS->LocateHandle (
                                ByProtocol,               // IN EFI_LOCATE_SEARCH_TYPE SearchType
                                &gAmdRasApeiProtocolGuid, // IN EFI_GUID *Protocol OPTIONAL
                                NULL,                     // IN VOID *SearchKey OPTIONAL
                                &BufferSize,              // IN OUT UINTN BufferSize
                                &hNewHandle               // OUT EFI_HANDLE *Buffer
                                );
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_PROTOCOL_ERROR;   // Error detected while trying to locate SMM Base Protocol
    }

    // Queries a handle to determine if it supports a specified protocol.
    Status = gBS->HandleProtocol (
                                  hNewHandle,                     // IN EFI_HANDLE Handle
                                  &gAmdRasApeiProtocolGuid,       // IN EFI_GUID *Protocol
                                  (VOID **) &AmdRasApeiProtocol   // OUT VOID *NewInterface
                                  );
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_PROTOCOL_ERROR;    // Error detected while trying to locate SMM Base Protocol
    }

    // Local ACPI Protocol
    Status = gBS->LocateProtocol (
                                  &gAcpiSupportGuid,
                                  NULL,
                                  (VOID **) &AcpiSupportProtocol
                                  );
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_PROTOCOL_ERROR;    // Error detected while trying to locate ACPI Support Protocol
    }

    //Add HEST table to the ACPI aware OS
    Status = AcpiSupportProtocol->SetAcpiTable (
                                                AcpiSupportProtocol,                        // IN EFI_ACPI_SUPPORT_PROTOCOL *This
                                                mApeiInterface->ApeiPrivData->ApeiHestTbl,  // IN VOID  *Table OPTIONAL
                                                TRUE,                                       // IN BOOLEAN Checksum
                                                EFI_ACPI_TABLE_VERSION_ALL,                 // IN EFI_ACPI_TABLE_VERSION Version
                                                &HestTblHandle                              // IN OUT UINTN *TableHandle
                                                );
    ASSERT_EFI_ERROR (Status);

    // Reinstalls a protocol interface on a device handle.
    Status = gBS->ReinstallProtocolInterface (
                                              hNewHandle,               // IN EFI_HANDLE Handle
                                              &gAmdRasApeiProtocolGuid, // IN EFI_GUID *Protocol
                                              AmdRasApeiProtocol,       // IN VOID *OldInterface
                                              AmdRasApeiProtocol        // IN VOID *NewInterface
                                              );
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_PROTOCOL_ERROR;    // Error detected while trying to locate SMM Base Protocol
    }

    // Create a callback event to be executed at ReadyToBoot to publish APEI tables to OS.
    Status = gBS->CreateEventEx (
                                 EFI_EVENT_NOTIFY_SIGNAL,
                                 EFI_TPL_NOTIFY,
                                 AddApeiTables,
                                 NULL,
                                 &gEfiEventReadyToBootGuid,
                                 &mEvtApeiReadyToBoot
                                 );
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return EFI_OUT_OF_RESOURCES;    // Error detected while trying to locate SMM Base Protocol
    }
  }

  return Status;
}
示例#4
0
/**
  Enrty point to DXE SMM Driver.

  @param  ImageHandle ImageHandle of the loaded driver.
  @param  SystemTable Pointer to the EFI System Table.

  @retval  EFI_SUCCESS One or more of the drivers returned a success code.
  @retval  !EFI_SUCESS The return status from the last driver entry point in the list.

**/
EFI_STATUS
EFIAPI
_ModuleEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS                 Status;
  EFI_LOADED_IMAGE_PROTOCOL  *LoadedImage;
  EFI_SMM_BASE_PROTOCOL      *SmmBase;
  BOOLEAN                    InSmm;
  EFI_DEVICE_PATH_PROTOCOL   *CompleteFilePath;
  EFI_DEVICE_PATH_PROTOCOL   *ImageDevicePath;
  EFI_HANDLE                 Handle;

  //
  // Cache a pointer to the Boot Services Table
  //
  gBS = SystemTable->BootServices;

  //
  // Retrieve SMM Base Protocol
  //
  Status = gBS->LocateProtocol (
                  &gEfiSmmBaseProtocolGuid,
                  NULL,
                  (VOID **) &SmmBase
                  );
  ASSERT_EFI_ERROR (Status);

  //
  // Check to see if we are already in SMM
  //
  SmmBase->InSmm (SmmBase, &InSmm);

  //
  //
  //
  if (!InSmm) {
    //
    // Retrieve the Loaded Image Protocol
    //
    Status = gBS->HandleProtocol (
                  ImageHandle,
                  &gEfiLoadedImageProtocolGuid,
                  (VOID*)&LoadedImage
                  );
    ASSERT_EFI_ERROR (Status);
    //
    // Retrieve the Device Path Protocol from the DeviceHandle from which this driver was loaded
    //
    Status = gBS->HandleProtocol (
                    LoadedImage->DeviceHandle,
                    &gEfiDevicePathProtocolGuid,
                    (VOID*)&ImageDevicePath
                    );
    ASSERT_EFI_ERROR (Status);

    //
    // Build the full device path to the currently execuing image
    //
    CompleteFilePath = SmmAppendDevicePath (ImageDevicePath, LoadedImage->FilePath);

    //
    // Load the image in memory to SMRAM; it will automatically generate the
    // SMI.
    //
    Status = SmmBase->Register (SmmBase, CompleteFilePath, LoadedImage->ImageBase, 0, &Handle, FALSE);
    ASSERT_EFI_ERROR (Status);
    //
    // Optionally install the unload handler
    //
    if (_gDriverUnloadImageCount > 0) {
      Status = gBS->HandleProtocol (
                      ImageHandle,
                      &gEfiLoadedImageProtocolGuid,
                      (VOID **)&LoadedImage
                      );
      ASSERT_EFI_ERROR (Status);
      LoadedImage->Unload = _DriverUnloadHandler;
    }

    return Status;
  }

  //
  // Call constructor for all libraries
  //
  ProcessLibraryConstructorList (ImageHandle, SystemTable);

  //
  // Call the list of driver entry points
  //
  Status = ProcessModuleEntryPointList (ImageHandle, SystemTable);
  if (EFI_ERROR (Status)) {
    ProcessLibraryDestructorList (ImageHandle, SystemTable);
  }

  return Status;
}
示例#5
0
/*********************************************************************************
 * Name: FchD3ColdInit
 *
 * Description
 *   Entry point of the AMD FCH D3Cold support driver
 *
 * Input
 *   ImageHandle : EFI Image Handle for the DXE driver
 *   SystemTable : pointer to the EFI system table
 *
 * Output
 *   EFI_SUCCESS : Module initialized successfully
 *   EFI_ERROR   : Initialization failed (see error for more details)
 *
 *********************************************************************************/
EFI_STATUS
EFIAPI
FchD3ColdInit (
  IN    EFI_HANDLE                  ImageHandle,
  IN    EFI_SYSTEM_TABLE            *SystemTable
  )
{
  EFI_STATUS                        Status;
  BOOLEAN                           InSmm;
  EFI_SMM_BASE_PROTOCOL             *SmmBase;
  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
  EFI_DEVICE_PATH_PROTOCOL          *ImageDevicePath;
  EFI_DEVICE_PATH_PROTOCOL          *CompleteFilePath;
  FCH_INIT_PROTOCOL                 *pAmdFchInitProtocol;
  PSP_RESUME_SERVICE_PROTOCOL       *pAmdPspResumeServiceProtocol;
  EFI_HANDLE                        SmmImageHandle;
  EFI_HANDLE                        DispatchHandle;
  VOID                              *Registration;

  gST      = SystemTable;
  gBS      = SystemTable->BootServices;

  Status = gBS->LocateProtocol (
                  &gFchInitProtocolGuid,
                  NULL,
                  &pAmdFchInitProtocol
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  if (pAmdFchInitProtocol->FchPolicy.Misc.FchCsSupport.FchCsD3Cold == FALSE) {
    return EFI_UNSUPPORTED;
  }

  InSmm    = FALSE;
  Status = gBS->LocateProtocol (
                  &gEfiSmmBaseProtocolGuid,
                  NULL,
                  &SmmBase
                  );

  if (EFI_ERROR (Status)) {
    return Status;
  }
  SmmBase->GetSmstLocation (
             SmmBase,
             &mSmst
             );
  SmmBase->InSmm (
             SmmBase,
             &InSmm
             );


  if (!InSmm) {
    //
    // Register event
    //
    EfiLibCreateProtocolNotifyEvent (
      &gFchAcpiProtocolGuid,
      EFI_TPL_CALLBACK,
      FchD3ColdAcpiConfigureNotify,
      NULL,
      &Registration
      );

    EfiLibCreateProtocolNotifyEvent (
      &gFchAcpiTableInstallGuid,
      EFI_TPL_CALLBACK,
      FchD3ColdAcpiInstallNotify,
      NULL,
      &Registration
      );

    //
    // Not in SMM. Load this driver's image into SMRAM
    //
    if (ImageHandle != NULL) {
      Status = gBS->HandleProtocol (
                      ImageHandle,
                      &gEfiLoadedImageProtocolGuid,
                      &LoadedImage
                      );
      if (EFI_ERROR (Status)) {
        return Status;
      }

      Status = gBS->HandleProtocol (
                      LoadedImage->DeviceHandle,
                      &gEfiDevicePathProtocolGuid,
                      (VOID*) &ImageDevicePath
                      );

      if (EFI_ERROR (Status)) {
        return Status;
      }

      CompleteFilePath = AppendDevicePath (
                           ImageDevicePath,
                           LoadedImage->FilePath
                           );

      // Load the image in memory to SMRAM, this automatically triggers SMI
      SmmBase->Register (
                 SmmBase,
                 CompleteFilePath,
                 NULL,
                 0,
                 &SmmImageHandle,
                 FALSE
                 );
    }
  } else {
    //
    // We're now in SMM!
    //
    Status = gBS->LocateProtocol (
                    &gFchInitProtocolGuid,
                    NULL,
                    &pAmdFchInitProtocol
                    );

    if (!EFI_ERROR (Status)) {
      EfiCopyMem (
        &gFchInitInSmm,
        pAmdFchInitProtocol,
        sizeof (FCH_INIT_PROTOCOL)
        );
    } else {
      return EFI_ABORTED;
    }

    Status = gBS->LocateProtocol (
                    &gPspResumeServiceProtocolGuid,
                    NULL,
                    &pAmdPspResumeServiceProtocol
                    );
    if (EFI_ERROR (Status)) {
      EfiLibCreateProtocolNotifyEvent (
        &gPspResumeServiceProtocolGuid,
        EFI_TPL_CALLBACK,
        FchCsResumeCallBackNotify,
        NULL,
        &Registration
        );
      return EFI_SUCCESS;
      //return Status;
    }
    Status = pAmdPspResumeServiceProtocol->Register (
                                             pAmdPspResumeServiceProtocol,
                                             &FchCsResumeCallBack,
                                             &gFchInitInSmm,
                                             0xFF,
                                             &DispatchHandle
                                             );
    return Status;
  }
  return EFI_SUCCESS;

}
示例#6
0
EFI_STATUS
PspSmmEntry (
  IN       EFI_HANDLE         ImageHandle,
  IN       EFI_SYSTEM_TABLE   *SystemTable
  )
{
  EFI_STATUS                      Status;
  BOOLEAN                         InSmm;
  EFI_SMM_BASE_PROTOCOL           *SmmBase;
  FCH_SMM_SX_DISPATCH_PROTOCOL    *SxDispatch;
  EFI_HANDLE                      SxHandle, SwHandle;
  FCH_SMM_SX_REGISTER_CONTEXT     SxRegisterContext;
  FCH_SMM_SW_DISPATCH_PROTOCOL    *AmdSwDispatch;
  FCH_SMM_SW_REGISTER_CONTEXT     SwRegisterContext;
  PSP_PLATFORM_PROTOCOL           *PspPlatfromProtocol;
  EFI_LOADED_IMAGE_PROTOCOL       *LoadedImage;
  EFI_PHYSICAL_ADDRESS            TempStackPtr;
  EFI_PHYSICAL_ADDRESS            AlignStackPtr;
  UINT32                          StackSize;

  //
  // Initialize EFI library
  //
  gST      = SystemTable;
  gBS      = SystemTable->BootServices;
  gRT      = gST->RuntimeServices;

  PSP_DEBUG ("Psp.Drv.PspSmm Enter\n");
  //If PSP feature turn off, exit the driver
  Status = CheckPspDevicePresent ();
  if (EFI_ERROR (Status)) {
    return EFI_UNSUPPORTED;
  }

  InSmm    = FALSE;
  Status = gBS->LocateProtocol (
                  &gEfiSmmBaseProtocolGuid,
                  NULL,
                  &SmmBase
                  );

  if (EFI_ERROR (Status)) {
    return Status;
  }
  SmmBase->GetSmstLocation (
             SmmBase,
             &mSmst
             );
  SmmBase->InSmm (
             SmmBase,
             &InSmm
             );


  if (!InSmm) {
    return (RegDriverToSmm (
              ImageHandle,
              SystemTable,
              SmmBase
              ));
  }

  //
  // We're now in SMM!
  //
  PSP_DEBUG ("\tRunning in SMM\n");
  //
  // We're now in SMM!
  //

  Status = gBS->LocateProtocol (
                  &gFchSmmSxDispatchProtocolGuid,
                  NULL,
                  &SxDispatch
                  );

  SxRegisterContext.Type  = AmdSxS3;
  SxRegisterContext.Phase = AmdSxEntry;
  SxRegisterContext.Order = 1;

  // Register with Smm driver to intercept Sx transition and inform Psp via mailbox in
  // that transition
  PSP_DEBUG ("\tRegister Sleep SMI\n");
  Status = SxDispatch->Register (
                          SxDispatch,
                          PspSxCallback,
                          &SxRegisterContext,
                          &SxHandle
                          );
  if (EFI_ERROR (Status)) {
    return Status;
  }
  // Below code is only needed if the referecen BIOS intend to use New S3 resume path (Using Dram instead of CAR)
  // Even if PSP initialize the DRAM, the OEM bios still has a choice to use the old resume path
  // i.e. do not write to MSR to perform resume. So add customization token to skip below code
  // for those designs
  //Locate Psp Platform Protocol to get customized information
  PSP_DEBUG ("\tLocate Psp Platform Protocol\n");
  Status = gBS->LocateProtocol (
                    &gPspPlatformProtocolGuid,
                    NULL,
                    &PspPlatfromProtocol
                    );

  if (EFI_ERROR (Status)) {
    return Status;
  }
  //Dump Platform protocol info
  PSP_DEBUG ("\tPSP_PLATFORM_PROTOCOL::\n");
  PSP_DEBUG ("\t\tCpuContextResumeEnable:0x%x\n", PspPlatfromProtocol->CpuContextResumeEnable);
  PSP_DEBUG ("\t\tSwSmiCmdtoBuildContext:0x%x\n", PspPlatfromProtocol->SwSmiCmdtoBuildContext);
  PSP_DEBUG ("\t\tBspStackSize:0x%x\n", PspPlatfromProtocol->BspStackSize);
  PSP_DEBUG ("\t\tApStackSize:0x%x\n", PspPlatfromProtocol->ApStackSize);
  PSP_DEBUG ("\t\tRsmHandOffInfo:&0x%x\n", PspPlatfromProtocol->RsmHandOffInfo);
  PSP_DEBUG ("\t\t\tGdtOffset:0x%x\n", PspPlatfromProtocol->RsmHandOffInfo->GdtOffset );
  PSP_DEBUG ("\t\t\tCodeSelector:0x%x\n", PspPlatfromProtocol->RsmHandOffInfo->CodeSelector);
  PSP_DEBUG ("\t\t\tDataSelector:0x%x\n", PspPlatfromProtocol->RsmHandOffInfo->DataSelector);
  PSP_DEBUG ("\t\t\tRsmEntryPoint:0x%x\n", PspPlatfromProtocol->RsmHandOffInfo->RsmEntryPoint);
  PSP_DEBUG ("\t\t\tEdxResumeSignature:0x%x\n", PspPlatfromProtocol->RsmHandOffInfo->EdxResumeSignature);

  //Copy the data to local copy to make it available at SMM space
  gBS->SetMem (&mPspPlatformProtocolCopy,
               sizeof (PSP_PLATFORM_PROTOCOL),
               0);

  gBS->CopyMem (&mPspPlatformProtocolCopy,
                PspPlatfromProtocol,
                sizeof (PSP_PLATFORM_PROTOCOL)
                 );

  if (mPspPlatformProtocolCopy.CpuContextResumeEnable != TRUE) {
    // We are not supporting CPU context resume. So we can bail from here
    return EFI_SUCCESS;
  }


  //Allocate Memory for hold PSP_SMM_RSM_MEM_INFO
  PSP_DEBUG ("\tAllocate Memory for New S3 Resume\n");

  Status = gBS->AllocatePool (
                EfiReservedMemoryType,
                sizeof (PSP_SMM_RSM_MEM_INFO),
                &mPspSmmRsmMemInfoPtr);
  ASSERT_EFI_ERROR (Status);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  gBS->SetMem (mPspSmmRsmMemInfoPtr,
             sizeof (PSP_SMM_RSM_MEM_INFO),
             0);

  //Allocate Memory for AGESA heap during SMM Resume
  //AGESA are request at 4K boudary
  Status = gBS->AllocatePages (
                  AllocateAnyPages,
                  EfiReservedMemoryType,
                  EFI_SIZE_TO_PAGES (SMM_RESUME_HEAP_SIZE),
                  &mPspSmmRsmMemInfoPtr->RsmHeapPtr);
  ASSERT_EFI_ERROR (Status);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  gBS->SetMem ((VOID *) (UINTN) mPspSmmRsmMemInfoPtr->RsmHeapPtr,
             SMM_RESUME_HEAP_SIZE,
             0);
  mPspSmmRsmMemInfoPtr->HeapSize = SMM_RESUME_HEAP_SIZE;

  //Allocate Memory for stack during SMM Resume
  //Allocate Double Stack Size for alignment
  StackSize = mPspPlatformProtocolCopy.BspStackSize + mPspPlatformProtocolCopy.ApStackSize * MAX_AP_COUNT;
  Status = gBS->AllocatePages (
                  AllocateAnyPages,
                  EfiReservedMemoryType,
                  EFI_SIZE_TO_PAGES (2 * StackSize),
                  &TempStackPtr);
  PSP_DEBUG ("Allocate TempStack 0x%x Size 0x%x\n", TempStackPtr, 2 * StackSize);

  ASSERT_EFI_ERROR (Status);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  gBS->SetMem ((VOID *) (UINTN) TempStackPtr,
             2 * StackSize,
             0);

  //Align on Stack Size boundary
  AlignStackPtr = ((TempStackPtr + mPspPlatformProtocolCopy.BspStackSize) & (~(mPspPlatformProtocolCopy.BspStackSize - 1)));

  //Free Unused Pages
  if (AlignStackPtr - TempStackPtr) {
    PSP_DEBUG ("Free 0x%x Size 0x%x\n", TempStackPtr, (AlignStackPtr - TempStackPtr));
    gBS->FreePages (TempStackPtr, (UINTN)EFI_SIZE_TO_PAGES (AlignStackPtr - TempStackPtr));
  }
  PSP_DEBUG ("Free 0x%x Size 0x%x\n", AlignStackPtr + StackSize, (StackSize - (AlignStackPtr - TempStackPtr)));
  gBS->FreePages (AlignStackPtr + StackSize, (UINTN)EFI_SIZE_TO_PAGES (StackSize - (AlignStackPtr - TempStackPtr)));

  mPspSmmRsmMemInfoPtr->StackPtr = AlignStackPtr;
  PSP_DEBUG ("AlignStackPtr 0x%x\n", AlignStackPtr);

  mPspSmmRsmMemInfoPtr->BspStackSize = mPspPlatformProtocolCopy.BspStackSize;
  mPspSmmRsmMemInfoPtr->ApStackSize = mPspPlatformProtocolCopy.ApStackSize;

  //Allocate Memory for temporary storage during SMM Resume
  Status = gBS->AllocatePages (
                  AllocateAnyPages,
                  EfiReservedMemoryType,
                  EFI_SIZE_TO_PAGES (SMM_RESUME_TEMP_REGION_SIZE),
                  &mPspSmmRsmMemInfoPtr->TempRegionPtr);
  ASSERT_EFI_ERROR (Status);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  mPspSmmRsmMemInfoPtr->TempRegionSize = SMM_RESUME_TEMP_REGION_SIZE;
  //Dump result of memory allocation
  PSP_DEBUG ("\tPspSmmRsmMemInfo::\n");
  PSP_DEBUG ("\t\tStackPtr:0x%x BspStackSize:0x%x ApStackSize:0x%x\n",
              mPspSmmRsmMemInfoPtr->StackPtr,
              mPspSmmRsmMemInfoPtr->BspStackSize,
              mPspSmmRsmMemInfoPtr->ApStackSize);
  PSP_DEBUG ("\t\tRsmHeapPtr:0x%x HeapSize:0x%x\n",
              mPspSmmRsmMemInfoPtr->RsmHeapPtr,
              mPspSmmRsmMemInfoPtr->HeapSize);
  PSP_DEBUG ("\t\tTempRegionPtr:0x%x TempRegionSize:0x%x\n",
              mPspSmmRsmMemInfoPtr->TempRegionPtr,
              mPspSmmRsmMemInfoPtr->TempRegionSize);

  Status = gBS->LocateProtocol (
                  &gFchSmmSwDispatchProtocolGuid,
                  NULL,
                  &AmdSwDispatch
                  );

  ASSERT_EFI_ERROR (Status);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  // Hook for software SMI to prepare CPU context for Smm resume during S3-resume
  PSP_DEBUG ("\tRegister SW SMI for prepare CPU resume context\n");
  SwRegisterContext.AmdSwValue  = mPspPlatformProtocolCopy.SwSmiCmdtoBuildContext;
  SwRegisterContext.Order       = 0x80;
  Status = AmdSwDispatch->Register (
                            AmdSwDispatch,
                            PspSmmSwSmiCallBack,
                            &SwRegisterContext,
                            &SwHandle
                            );

  ASSERT_EFI_ERROR (Status);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Publish protocol for others to register for resume time callback
  //
  PSP_DEBUG ("\tPublish resume register protocol\n");
  InstallPspResumeCallbackProtocol ();

  //Send Resume info to PSP to prevent resume module be tampered
  Status = gBS->HandleProtocol (
                    ImageHandle,
                    &gEfiLoadedImageProtocolGuid,
                    &LoadedImage
                    );
  ASSERT_EFI_ERROR (Status);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  PSP_DEBUG ("\tASRF.Base:0x%x ASRF.Size:0x%x\n", LoadedImage->ImageBase, LoadedImage->ImageSize);
  Status = PspMboxBiosCmdResumeInfo (
                  (UINT64) LoadedImage->ImageBase,
                  LoadedImage->ImageSize);

  ASSERT_EFI_ERROR (Status);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  PSP_DEBUG ("PspSmm Exit\n");

  return Status;
}
示例#7
0
EFI_STATUS
EfiInitializeSmmDriverLib (
  IN EFI_HANDLE           ImageHandle,
  IN EFI_SYSTEM_TABLE     *SystemTable
  )
/*++

Routine Description:

  Intialize runtime Driver Lib if it has not yet been initialized. 

Arguments:

  ImageHandle     - The firmware allocated handle for the EFI image.
  
  SystemTable     - A pointer to the EFI System Table.

Returns: 

  EFI_STATUS always returns EFI_SUCCESS except EFI_ALREADY_STARTED if already started.

--*/
{
  EFI_STATUS               Status;
  EFI_SMM_BASE_PROTOCOL    *SmmBase;

  if (mRuntimeLibInitialized) {
    return EFI_ALREADY_STARTED;
  }

  mRuntimeLibInitialized  = TRUE;

  gST = SystemTable;
  ASSERT (gST != NULL);

  gBS = SystemTable->BootServices;
  ASSERT (gBS != NULL);
  mRT = SystemTable->RuntimeServices;
  ASSERT (mRT != NULL);

  //
  // Check whether it is in SMM mode.
  //
  Status  = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID**) &SmmBase);
  if (!EFI_ERROR (Status)) {
    SmmBase->InSmm (SmmBase, &mInSmm);
  }

  //
  // Directly locate SmmStatusCode protocol
  //
  Status = gBS->LocateProtocol (&gEfiSmmStatusCodeProtocolGuid, NULL, (VOID**) &gSmmStatusCodeProtocol);
  if (EFI_ERROR (Status)) {
    gSmmStatusCodeProtocol = NULL;
  }

  Status  = gBS->LocateProtocol (&gEfiCpuIoProtocolGuid, NULL, (VOID **) &gCpuIo);
  if (EFI_ERROR (Status)) {
    gCpuIo = NULL;
  }

  return EFI_SUCCESS;
}
示例#8
0
EFI_STATUS
ImcControlEntry (
  IN       EFI_HANDLE         ImageHandle,
  IN       EFI_SYSTEM_TABLE   *SystemTable
  )

{
  EFI_STATUS                      Status;
  BOOLEAN                         InSmm;
  EFI_SMM_BASE_PROTOCOL           *SmmBase;
  EFI_LOADED_IMAGE_PROTOCOL       *LoadedImage;
  EFI_DEVICE_PATH_PROTOCOL        *ImageDevicePath;
  EFI_DEVICE_PATH_PROTOCOL        *CompleteFilePath;
  FCH_INIT_PROTOCOL               *AmdFchInit;
  EFI_HANDLE                      SmmImageHandle;

  //
  // Initialize EFI library
  //
  InSmm    = FALSE;
  gST      = SystemTable;
  gBS      = SystemTable->BootServices;

  Status = gBS->LocateProtocol (
                  &gEfiSmmBaseProtocolGuid,
                  NULL,
                  &SmmBase
                  );

  if (EFI_ERROR (Status)) {
    return Status;
  }
  SmmBase->GetSmstLocation (
             SmmBase,
             &mSmst
             );
  mSmmIo = &mSmst->SmmIo;
  SmmBase->InSmm (
             SmmBase,
             &InSmm
             );


  if (!InSmm) {
    //
    // Not in SMM. Load this driver's image into SMRAM
    //
    if (ImageHandle != NULL) {
      Status = gBS->HandleProtocol (
                      ImageHandle,
                      &gEfiLoadedImageProtocolGuid,
                      &LoadedImage
                      );
      if (EFI_ERROR (Status)) {
        return Status;
      }

      Status = gBS->HandleProtocol (
                      LoadedImage->DeviceHandle,
                      &gEfiDevicePathProtocolGuid,
                      (VOID*) &ImageDevicePath
                      );

      if (EFI_ERROR (Status)) {
        return Status;
      }

      CompleteFilePath = AppendDevicePath (
                           ImageDevicePath,
                           LoadedImage->FilePath
                           );

      // Load the image in memory to SMRAM, this automatically triggers SMI
      SmmBase->Register (
                 SmmBase,
                 CompleteFilePath,
                 NULL,
                 0,
                 &SmmImageHandle,
                 FALSE
                 );
    }
  } else {
    //
    // We're now in SMM!
    //
    Status = gBS->LocateProtocol (
                    &gFchInitProtocolGuid,
                    NULL,
                    &AmdFchInit
                    );
    if (!EFI_ERROR (Status)) {
      mImcThermalEnable = AmdFchInit->FchPolicy.Imc.EcStruct.IMCFUNSupportBitMap;
    } else {
      return EFI_ABORTED;
    }

    Status = ImcControlSmmRegister ();
    return Status;

  }
  return Status;
}
示例#9
0
/********************************************************************************
 * Name: AmdFchWheaInitEntry
 *
 * Description
 *   AmdFchWheaInit Entrypoint
 *
 * Input
 *
 * Output
 *   EFI_UNSUPPORTED : unsupported function
 *
 *********************************************************************************/
EFI_STATUS
AmdFchWheaInitEntry (
  IN EFI_HANDLE                             ImageHandle,
  IN EFI_SYSTEM_TABLE                       *SystemTable
  )
{
  EFI_STATUS                                Status;
  BOOLEAN                                   InSmm;
  FCH_INIT_PROTOCOL                         *AmdFchInit;
  EFI_SMM_BASE_PROTOCOL                     *SmmBase;
  FCH_SMM_SW_DISPATCH_PROTOCOL              *AmdSwDispatch;
  FCH_SMM_SW_REGISTER_CONTEXT               SwRegisterContext;
  EFI_HANDLE                                SwHandle;
  FCH_SMM_MISC_DISPATCH_PROTOCOL            *AmdFchSmmMiscDispatch;
  FCH_SMM_MISC_REGISTER_CONTEXT             MiscRegisterContext;
  EFI_HANDLE                                MiscHandle;
  EFI_SMM_SYSTEM_TABLE                      *mSmst;
  EFI_LOADED_IMAGE_PROTOCOL                 *LoadedImage;
  EFI_DEVICE_PATH_PROTOCOL                  *ImageDevicePath;
  EFI_DEVICE_PATH_PROTOCOL                  *CompleteFilePath;
  EFI_HANDLE                                SmmImageHandle;
  EFI_EVENT                                 InstallAmdTableEvent;
  EFI_HANDLE                                Handle;
  UINT8                                     *buffer;

  InSmm    = FALSE;
  DxeInitializeDriverLib (ImageHandle, SystemTable);

  Status = gBS->LocateProtocol (
                  &gFchInitProtocolGuid,
                  NULL,
                  &AmdFchInit
                  );
  ASSERT_EFI_ERROR (Status);

  if (AmdFchInit->FchPolicy.Gpp.PcieAer == 0) {
    return Status;
  }

  Status = gBS->LocateProtocol (
                  &gEfiSmmBaseProtocolGuid,
                  NULL,
                  &SmmBase
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  SmmBase->GetSmstLocation (
             SmmBase,
             &mSmst
             );
  SmmBase->InSmm (
             SmmBase,
             &InSmm
             );

  if (!InSmm) {
    Status = EfiCreateEventReadyToBoot (
               EFI_TPL_CALLBACK,
               AmdWheaCheckInstallTables,
               NULL,
               &InstallAmdTableEvent
               );

    //
    //  Allocate memory and Initialize for Data block
    //
    Status = gBS->AllocatePool (
                    EfiReservedMemoryType,
                    sizeof (AMD_FCH_WHEA_EINJ_BUFFER),
                    (VOID **)&buffer
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }
    EfiZeroMem (buffer, sizeof (AMD_FCH_WHEA_EINJ_BUFFER));

    mEinjData = (AMD_FCH_WHEA_EINJ_BUFFER *)buffer;
    mEinjData->Valid             = FALSE;
    mEinjData->PlatformEinjValid = FALSE;

    //
    //  Allocate memory and Initialize for Error Data block
    //
    Status = gBS->AllocatePool (
                    EfiReservedMemoryType,
                    MAX_ERROR_BLOCK_SIZE,
                    (VOID **)&buffer
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }
    EfiZeroMem (buffer, MAX_ERROR_BLOCK_SIZE);

    mEinjData->AmdHwErrBlk = (GENERIC_ERROR_STATUS_BLOCK *)buffer;

    AmdErrBlkAddressUpdate ();

    Handle = ImageHandle;
    Status = gBS->InstallProtocolInterface (
                    &Handle,
                    &mEfiAmdFchWheaDataGuid,
                    EFI_NATIVE_INTERFACE,
                    mEinjData
                    );
    if (EFI_ERROR (Status)) {
      return (Status);
    }

    if (ImageHandle != NULL) {
      Status = gBS->HandleProtocol (
                      ImageHandle,
                      &gEfiLoadedImageProtocolGuid,
                      &LoadedImage
                      );
      if (EFI_ERROR (Status)) {
        return Status;
      }

      Status = gBS->HandleProtocol (
                      LoadedImage->DeviceHandle,
                      &gEfiDevicePathProtocolGuid,
                      (VOID*) &ImageDevicePath
                      );
      if (EFI_ERROR (Status)) {
        return Status;
      }

      CompleteFilePath = AppendDevicePath (
                           ImageDevicePath,
                           LoadedImage->FilePath
                           );

      // Load the image in memory to SMRAM, this automatically triggers SMI
      SmmBase->Register (
                 SmmBase,
                 CompleteFilePath,
                 NULL,
                 0,
                 &SmmImageHandle,
                 FALSE
                 );
    }
  } else {
    Status = gBS->LocateProtocol (
                    &mEfiAmdFchWheaDataGuid,
                    NULL,
                    &mEinjData
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }

    Status = gBS->LocateProtocol (
                    &gFchSmmSwDispatchProtocolGuid,
                    NULL,
                    &AmdSwDispatch
                    );
    ASSERT_EFI_ERROR (Status);

    SwRegisterContext.AmdSwValue  = EINJ_TRIGGER_ACTION_SWSMI;
    Status = AmdSwDispatch->Register (
                              AmdSwDispatch,
                              AmdSmiEinjTriggerActionCallBack,
                              &SwRegisterContext,
                              &SwHandle
                              );
    if (EFI_ERROR (Status)) {
      return Status;
    }

    Status = gBS->LocateProtocol (
                    &gFchSmmMiscDispatchProtocolGuid,
                    NULL,
                    &AmdFchSmmMiscDispatch
                    );
    ASSERT_EFI_ERROR (Status);

    MiscRegisterContext.SmiStatusReg = FCH_SMI_REG88;
    MiscRegisterContext.SmiStatusBit = BIT21;
    MiscRegisterContext.Order        = 0x80;
    Status = AmdFchSmmMiscDispatch->Register (
                                      AmdFchSmmMiscDispatch,
                                      AmdMiscFchWheaHwSmiCallback,
                                      &MiscRegisterContext,
                                      &MiscHandle
                                      );

    MiscRegisterContext.SmiStatusReg = FCH_SMI_REG88;
    MiscRegisterContext.SmiStatusBit = BIT22;
    MiscRegisterContext.Order        = 0x80;
    Status = AmdFchSmmMiscDispatch->Register (
                                      AmdFchSmmMiscDispatch,
                                      AmdMiscFchWheaHwSmiCallback,
                                      &MiscRegisterContext,
                                      &MiscHandle
                                      );

    MiscRegisterContext.SmiStatusReg = FCH_SMI_REG88;
    MiscRegisterContext.SmiStatusBit = BIT23;
    MiscRegisterContext.Order        = 0x80;
    Status = AmdFchSmmMiscDispatch->Register (
                                      AmdFchSmmMiscDispatch,
                                      AmdMiscFchWheaHwSmiCallback,
                                      &MiscRegisterContext,
                                      &MiscHandle
                                      );

    MiscRegisterContext.SmiStatusReg = FCH_SMI_REG88;
    MiscRegisterContext.SmiStatusBit = BIT24;
    MiscRegisterContext.Order        = 0x80;
    Status = AmdFchSmmMiscDispatch->Register (
                                      AmdFchSmmMiscDispatch,
                                      AmdMiscFchWheaHwSmiCallback,
                                      &MiscRegisterContext,
                                      &MiscHandle
                                      );

    ACPIMMIO32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REGB4) &= ~(BIT11 + BIT13 + BIT15 + BIT17);
    ACPIMMIO32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REGB4) |= (BIT10 + BIT12 + BIT14 + BIT16);
  }
  return Status;
}