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; }
EFI_STATUS EFIAPI InitializePlatformSmm ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; UINT8 Index; EFI_HANDLE Handle; EFI_SMM_POWER_BUTTON_DISPATCH_CONTEXT PowerButtonContext; EFI_SMM_POWER_BUTTON_DISPATCH_PROTOCOL *PowerButtonDispatch; EFI_SMM_ICHN_DISPATCH_CONTEXT IchnContext; EFI_SMM_ICHN_DISPATCH_PROTOCOL *IchnDispatch; EFI_SMM_SX_DISPATCH_PROTOCOL *SxDispatch; EFI_SMM_SX_DISPATCH_CONTEXT EntryDispatchContext; EFI_SMM_SW_DISPATCH_PROTOCOL *SwDispatch; EFI_SMM_SW_DISPATCH_CONTEXT SwContext; UINTN VarSize; EFI_BOOT_MODE BootMode; Handle = NULL; // // Locate the Global NVS Protocol. // Status = gBS->LocateProtocol ( &gEfiGlobalNvsAreaProtocolGuid, NULL, (void **)&mGlobalNvsAreaPtr ); ASSERT_EFI_ERROR (Status); // // Get the ACPI Base Address // mAcpiBaseAddr = PchLpcPciCfg16( R_PCH_LPC_ACPI_BASE ) & B_PCH_LPC_ACPI_BASE_BAR; VarSize = sizeof(SYSTEM_CONFIGURATION); Status = SystemTable->RuntimeServices->GetVariable( L"Setup", &gEfiSetupVariableGuid, NULL, &VarSize, &mSystemConfiguration ); if (EFI_ERROR (Status) || VarSize != sizeof(SYSTEM_CONFIGURATION)) { //The setup variable is corrupted VarSize = sizeof(SYSTEM_CONFIGURATION); Status = SystemTable->RuntimeServices->GetVariable( L"SetupRecovery", &gEfiSetupVariableGuid, NULL, &VarSize, &mSystemConfiguration ); ASSERT_EFI_ERROR (Status); } if (!EFI_ERROR(Status)) { mAcLossVariable = mSystemConfiguration.StateAfterG3; // // If LAN is disabled, WOL function should be disabled too. // if (mSystemConfiguration.Lan == 0x01){ mWakeOnLanS5Variable = mSystemConfiguration.WakeOnLanS5; } else { mWakeOnLanS5Variable = FALSE; } mWakeOnRtcVariable = mSystemConfiguration.WakeOnRtcS5; } BootMode = GetBootModeHob (); // // Get the Power Button protocol // Status = gBS->LocateProtocol( &gEfiSmmPowerButtonDispatchProtocolGuid, NULL, (void **)&PowerButtonDispatch ); ASSERT_EFI_ERROR(Status); if (BootMode != BOOT_ON_FLASH_UPDATE) { // // Register for the power button event // PowerButtonContext.Phase = PowerButtonEntry; Status = PowerButtonDispatch->Register( PowerButtonDispatch, PowerButtonCallback, &PowerButtonContext, &Handle ); ASSERT_EFI_ERROR(Status); } // // Get the Sx dispatch protocol // Status = gBS->LocateProtocol ( &gEfiSmmSxDispatchProtocolGuid, NULL, (void **)&SxDispatch ); ASSERT_EFI_ERROR(Status); // // Register entry phase call back function // EntryDispatchContext.Type = SxS3; EntryDispatchContext.Phase = SxEntry; Status = SxDispatch->Register ( SxDispatch, (EFI_SMM_SX_DISPATCH)SxSleepEntryCallBack, &EntryDispatchContext, &Handle ); EntryDispatchContext.Type = SxS4; Status = SxDispatch->Register ( SxDispatch, S4S5CallBack, &EntryDispatchContext, &Handle ); ASSERT_EFI_ERROR(Status); EntryDispatchContext.Type = SxS5; Status = SxDispatch->Register ( SxDispatch, S4S5CallBack, &EntryDispatchContext, &Handle ); ASSERT_EFI_ERROR(Status); Status = SxDispatch->Register ( SxDispatch, S5SleepAcLossCallBack, &EntryDispatchContext, &Handle ); ASSERT_EFI_ERROR(Status); // // Get the Sw dispatch protocol // Status = gBS->LocateProtocol ( &gEfiSmmSwDispatchProtocolGuid, NULL, (void **)&SwDispatch ); ASSERT_EFI_ERROR(Status); // // Register ACPI enable handler // SwContext.SwSmiInputValue = ACPI_ENABLE; Status = SwDispatch->Register ( SwDispatch, EnableAcpiCallback, &SwContext, &Handle ); ASSERT_EFI_ERROR(Status); // // Register ACPI disable handler // SwContext.SwSmiInputValue = ACPI_DISABLE; Status = SwDispatch->Register ( SwDispatch, DisableAcpiCallback, &SwContext, &Handle ); ASSERT_EFI_ERROR(Status); // // Register for SmmReadyToBootCallback // SwContext.SwSmiInputValue = SMI_SET_SMMVARIABLE_PROTOCOL; Status = SwDispatch->Register( SwDispatch, SmmReadyToBootCallback, &SwContext, &Handle ); ASSERT_EFI_ERROR(Status); // // Get the ICHn protocol // Status = gBS->LocateProtocol( &gEfiSmmIchnDispatchProtocolGuid, NULL, (void **)&IchnDispatch ); ASSERT_EFI_ERROR(Status); // // Register for the events that may happen that we do not care. // This is true for SMI related to TCO since TCO is enabled by BIOS WP // for (Index = 0; Index < sizeof(mTco1Sources)/sizeof(UINT8); Index++) { IchnContext.Type = mTco1Sources[Index]; Status = IchnDispatch->Register( IchnDispatch, (EFI_SMM_ICHN_DISPATCH)DummyTco1Callback, &IchnContext, &Handle ); ASSERT_EFI_ERROR( Status ); } // // Lock TCO_EN bit. // IoWrite16( mAcpiBaseAddr + R_PCH_TCO_CNT, IoRead16( mAcpiBaseAddr + R_PCH_TCO_CNT ) | B_PCH_TCO_CNT_LOCK ); // // Set to power on from G3 dependent on WOL instead of AC Loss variable in order to support WOL from G3 feature. // // // Set wake from G3 dependent on AC Loss variable and Wake On LAN variable. // This is because no matter how, if WOL enabled or AC Loss variable not disabled, the board needs to wake from G3 to program the LAN WOL settings. // This needs to be done after LAN enable/disable so that the PWR_FLR state clear not impacted the WOL from G3 feature. // if (mAcLossVariable != 0x00) { SetAfterG3On (TRUE); } else { SetAfterG3On (FALSE); } return EFI_SUCCESS; }