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