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