From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by mx.groups.io with SMTP id smtpd.web08.849.1646952110863190430 for ; Thu, 10 Mar 2022 14:41:52 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=emVRnJYe; spf=pass (domain: intel.com, ip: 134.134.136.31, mailfrom: isaac.w.oram@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646952112; x=1678488112; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ItXnlpF0bfoIM+IiSQWYtmZ4Y31m0l+qk9eqnvPxGys=; b=emVRnJYecMtFlgF7uQY7pgpli2G3CURfVxO451PLATdTnusw9E+innJ8 EgyMV7XkckWEdIVDeEFrJ/vK5M23/uls/08yu7sSn9JXkdWzIhUe7VqJ5 DPEy1owjdvjNnMdr8uG8sdgHlCtMXt11wmAR4+m36aHTlLSkC4MkHshy6 hbsQjpWkHMdnUP6Qj5BfAbyA3ak5MzPM+V0yMO3P9CwYuJyCRFf/2YKxz jS2+TTIFG+3p38Tj65S1lWFCyudBw/gzb2C1Uz7egVtJ6XkaaDK0PdV81 1lH+j58cCZpst6orIX/RAbqJ2iifCXOkEoK+HI+sDLFcFfcuHsbCHD8tF A==; X-IronPort-AV: E=McAfee;i="6200,9189,10282"; a="316121257" X-IronPort-AV: E=Sophos;i="5.90,171,1643702400"; d="scan'208";a="316121257" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Mar 2022 14:41:35 -0800 X-IronPort-AV: E=Sophos;i="5.90,171,1643702400"; d="scan'208";a="644643389" Received: from iworam-desk.amr.corp.intel.com ([10.7.150.60]) by orsmga004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Mar 2022 14:41:35 -0800 From: "Oram, Isaac W" To: devel@edk2.groups.io Cc: Nate DeSimone , Chasel Chiu Subject: [edk2-devel][edk2-platforms][PATCH V1 8/9] WhitleyOpenBoardPkg/AcpiPlatform: Add driver for publishing ACPI tables Date: Thu, 10 Mar 2022 14:41:13 -0800 Message-Id: X-Mailer: git-send-email 2.27.0.windows.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit AcpiPlatform DXE driver loads and patches ACPI tables before publishing. Cc: Nate DeSimone Cc: Chasel Chiu Signed-off-by: Isaac Oram --- Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.c | 754 +++++++++ Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.h | 117 ++ Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.inf | 107 ++ Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformHooks.c | 384 +++++ Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformHooks.h | 51 + Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformUtils.c | 133 ++ Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformUtils.h | 66 + Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformVTDHooks.c | 1762 ++++++++++++++++++++ Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec | 11 +- Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc | 3 + Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf | 3 + Platform/Intel/WhitleyOpenBoardPkg/Uba/UbaMain/StaticSkuDataDxe/Readme.md | 1 + Platform/Intel/WhitleyOpenBoardPkg/WilsonCityRvp/AmlOffsets/AmlOffsets.inf | 2 +- 13 files changed, 3388 insertions(+), 6 deletions(-) diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.c new file mode 100644 index 0000000000..1648029bd1 --- /dev/null +++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.c @@ -0,0 +1,754 @@ +/** @file + ACPI Platform Driver + + @copyright + Copyright 1999 - 2020 Intel Corporation.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "AcpiPlatform.h" +#include "AcpiPlatformUtils.h" +#include "AcpiPlatformHooks.h" +#include +#include +#include +#include + + +#ifndef __GNUC__ +#pragma optimize("", off) +#endif //__GNUC__ + +extern SOCKET_IIO_CONFIGURATION mSocketIioConfiguration; +extern SOCKET_POWERMANAGEMENT_CONFIGURATION mSocketPowermanagementConfiguration; +extern SOCKET_PROCESSORCORE_CONFIGURATION mSocketProcessorCoreConfiguration; +extern EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE *mSpcrTable; +extern EFI_GUID gEfiGlobalVariableGuid; +extern EFI_GUID gEfiPmSsdtTableStorageGuid; + +BIOS_ACPI_PARAM *mAcpiParameter = NULL; +BOOLEAN mFirstNotify; +SYSTEM_CONFIGURATION mSystemConfiguration; +PCH_SETUP mPchSetup; + +UINT8 mKBPresent = 0; +UINT8 mMousePresent = 0; +EFI_IIO_UDS_PROTOCOL *mIioUds2 = NULL; +extern CPU_CSR_ACCESS_VAR *mCpuCsrAccessVarPtr; +UINT8 mPStateEnable = 0; + + +VOID +EFIAPI +AcpiOnPciEnumCmplCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid, NULL, &Context); + if (EFI_ERROR (Status)) { + // + // Skip the first dummy event signal. + // + return; + } + gBS->CloseEvent (Event); + + DEBUG ((DEBUG_INFO, "[ACPI] %a\n", __FUNCTION__)); + AcpiVtdTablesInstall (); +} + + +VOID +EFIAPI +AcpiOnEndOfDxeCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + DEBUG ((DEBUG_INFO, "[ACPI] %a\n", __FUNCTION__)); + // + // Installing ACPI Tables: NFIT, PCAT + // + InstallAndPatchAcpiTable (NVDIMM_FW_INTERFACE_TABLE_SIGNATURE); + InstallAndPatchAcpiTable (NVDIMM_PLATFORM_CONFIG_ATTRIBUTE_TABLE_SIGNATURE); +} + + +// +// Enable SCI for ACPI aware OS at ExitBootServices +// +VOID +EFIAPI +AcpiOnExitBootServicesCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINT16 Pm1Cnt; + + gBS->CloseEvent (Event); + + DEBUG ((DEBUG_INFO, "[ACPI] %a\n", __FUNCTION__)); + // + // Enable SCI + // + Pm1Cnt = IoRead16 (mAcpiParameter->PmBase + R_ACPI_IO_PM1_CNT); + Pm1Cnt |= B_ACPI_IO_PM1_CNT_SCI_EN; + IoWrite16 (mAcpiParameter->PmBase + R_ACPI_IO_PM1_CNT, Pm1Cnt); +} + +/** + Disables the SW SMI Timer. + ACPI events are disabled and ACPI event status is cleared. + SCI mode is then enabled. + + Disable SW SMI Timer + + Clear all ACPI event status and disable all ACPI events + Disable PM sources except power button + Clear status bits + + Disable GPE0 sources + Clear status bits + + Disable GPE1 sources + Clear status bits + + Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4) + + Enable SCI + + @param Event - not used + @param Context - not used + + @retval None +**/ +STATIC +VOID +AcpiEnableAtReadyToBoot ( + VOID + ) +{ + UINT32 SmiEn; + UINT8 Data8; + UINT16 Pm1En; + + ASSERT (mAcpiParameter->PmBase != 0); + + SmiEn = IoRead32 (mAcpiParameter->PmBase + R_ACPI_IO_SMI_EN); + + // + // Disable SW SMI Timer and legacy USB + // + SmiEn &= ~(B_ACPI_IO_SMI_EN_SWSMI_TMR | B_ACPI_IO_SMI_EN_LEGACY_USB | B_ACPI_IO_SMI_EN_LEGACY_USB2); + + + // + // And enable SMI on write to B_ACPI_IO_PM1_CNT_SLP_EN when SLP_TYP is written + // + SmiEn |= B_ACPI_IO_SMI_EN_ON_SLP_EN; + IoWrite32(mAcpiParameter->PmBase + R_ACPI_IO_SMI_EN, SmiEn); + + // + // Disable PM sources except power button + // + + Pm1En = B_ACPI_IO_PM1_EN_PWRBTN; + IoWrite16(mAcpiParameter->PmBase + R_ACPI_IO_PM1_EN, Pm1En); + + // + // Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4) + // + Data8 = RTC_ADDRESS_REGISTER_D; + IoWrite8(R_IOPORT_CMOS_STANDARD_INDEX, Data8); + Data8 = 0x0; + IoWrite8(R_IOPORT_CMOS_STANDARD_DATA, Data8); + + // + // Do platform specific stuff for ACPI enable SMI + // + + +} + +/** + Executes ACPI Platform actions related with ready to boot event + + @param Event - not used + @param Context - not used + + @retval None +**/ +STATIC +VOID +EFIAPI +AcpiOnReadyToBootCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EFI_ACPI_DESCRIPTION_HEADER Table = {0}; + EFI_ACPI_TABLE_VERSION TableVersion; + UINTN TableHandle; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + EFI_CPUID_REGISTER CpuidRegisters; + SETUP_DATA SetupData; + UINT8 ARIForward; + + DYNAMIC_SI_LIBARY_PROTOCOL *DynamicSiLibraryProtocol = NULL; + + Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &DynamicSiLibraryProtocol); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return; + } + + if (mFirstNotify) { + return; + } + mFirstNotify = TRUE; + DEBUG ((DEBUG_INFO, "[ACPI] %a\n", __FUNCTION__)); + + Status = GetEntireConfig (&SetupData); + ASSERT_EFI_ERROR (Status); + CopyMem (&mSystemConfiguration, &(SetupData.SystemConfig), sizeof(SYSTEM_CONFIGURATION)); + CopyMem (&mSocketIioConfiguration, &(SetupData.SocketConfig.IioConfig), sizeof(SOCKET_IIO_CONFIGURATION)); + CopyMem (&mSocketPowermanagementConfiguration, &(SetupData.SocketConfig.PowerManagementConfig), sizeof(SOCKET_POWERMANAGEMENT_CONFIGURATION)); + CopyMem (&mSocketProcessorCoreConfiguration, &(SetupData.SocketConfig.SocketProcessorCoreConfiguration), sizeof(SOCKET_PROCESSORCORE_CONFIGURATION)); + CopyMem (&mPchSetup, &(SetupData.PchSetup), sizeof(PCH_SETUP)); + + mAcpiParameter->TpmEnable = mSystemConfiguration.TpmEnable; + + // + // CpuPm.Asl: External (CSEN, FieldUnitObj) + // + mAcpiParameter->CStateEnable = TRUE; + // + // CpuPm.Asl: External (C3EN, FieldUnitObj) + // + mAcpiParameter->C3Enable = mSocketPowermanagementConfiguration.C3Enable; + // + // CpuPm.Asl: External (C6EN, FieldUnitObj) + // + AsmCpuid (CPUID_MONITOR_MWAIT, &CpuidRegisters.RegEax, &CpuidRegisters.RegEbx, &CpuidRegisters.RegEcx, &CpuidRegisters.RegEdx); + // + // If C6 is not supported by CPU, disregard setup C6 knob value + // + if (((CpuidRegisters.RegEdx >> 12) & 0xF) > 0) { + if (mSocketPowermanagementConfiguration.C6Enable == PPM_AUTO) { + mAcpiParameter->C6Enable = 1; // POR Default = Enabled + } else { + mAcpiParameter->C6Enable = mSocketPowermanagementConfiguration.C6Enable; + } + } else { + mAcpiParameter->C6Enable = 0; + DEBUG ((DEBUG_INFO, "Cpu does not support C6 state\n")); + } + + if (mAcpiParameter->C6Enable && mAcpiParameter->C3Enable) { //C3 and C6 enable are exclusive + mAcpiParameter->C6Enable = 1; + mAcpiParameter->C3Enable = 0; + } + // + // CpuPm.Asl: External (C7EN, FieldUnitObj) + // + mAcpiParameter->C7Enable = 0; + // + // CpuPm.Asl: External (OSCX, FieldUnitObj) + // + mAcpiParameter->OSCX = mSocketPowermanagementConfiguration.OSCx; + // + // CpuPm.Asl: External (MWOS, FieldUnitObj) + // + mAcpiParameter->MonitorMwaitEnable = 1; + // + // CpuPm.Asl: External (PSEN, FieldUnitObj) + // + mAcpiParameter->PStateEnable = mPStateEnable; + // + // CpuPm.Asl: External (HWAL, FieldUnitObj) + // + mAcpiParameter->HWAllEnable = mSocketPowermanagementConfiguration.ProcessorEistPsdFunc; + + mAcpiParameter->KBPresent = mKBPresent; + mAcpiParameter->MousePresent = mMousePresent; + mAcpiParameter->TStateEnable = mSocketPowermanagementConfiguration.TStateEnable; + // + // Debug mode indicator for Acpi use + // + mAcpiParameter->DebugModeIndicator = (UINT8)PcdGet8 (PcdDebugModeEnable); + DEBUG ((DEBUG_ERROR, "DebugModeIndicator = %x\n", mAcpiParameter->DebugModeIndicator)); + + // + // Fine grained T state + // + AsmCpuid (CPUID_THERMAL_POWER_MANAGEMENT, &CpuidRegisters.RegEax, &CpuidRegisters.RegEbx, &CpuidRegisters.RegEcx, &CpuidRegisters.RegEdx); + if ((((CPUID_THERMAL_POWER_MANAGEMENT_EAX*)&CpuidRegisters.RegEax)->Bits.ECMD) && mSocketPowermanagementConfiguration.TStateEnable) { + mAcpiParameter->TStateFineGrained = 1; + } + if (((CPUID_THERMAL_POWER_MANAGEMENT_EAX*)&CpuidRegisters.RegEax)->Bits.HWP_Notification != 0) { + mAcpiParameter->HwpInterrupt = 1; + } + // + // CpuPm.Asl: External (HWEN, FieldUnitObj) + // + mAcpiParameter->HWPMEnable = DetectHwpFeature (); + + mAcpiParameter->EmcaEn = mSystemConfiguration.EmcaEn; + mAcpiParameter->WheaSupportEn = mSystemConfiguration.WheaSupportEn; + + mAcpiParameter->PcieAcpiHotPlugEnable = (UINT8) (BOOLEAN) (mSocketIioConfiguration.PcieAcpiHotPlugEnable != 0); + // + // Initialize USB3 mode from setup data + // + // If mode != manual control + // just copy mode from setup + // + if (mPchSetup.PchUsbManualMode != 1) { + mAcpiParameter->XhciMode = mPchSetup.PchUsbManualMode; + } + + // + // Get ACPI IO Base Address + // + mAcpiParameter->PmBase = DynamicSiLibraryProtocol->PmcGetAcpiBase (); + DEBUG ((DEBUG_INFO, "ACPI IO Base Address = %x\n", mAcpiParameter->PmBase)); + + // + // When X2APIC enabled and VTD support enabled, Enable ApicIdOverrided parameter to update ACPI table. + // + if (mSocketIioConfiguration.VTdSupport && mSocketProcessorCoreConfiguration.ProcessorX2apic) { + mAcpiParameter->ApicIdOverrided = 1; + } + + // + // Find the AcpiTable protocol + // + Status = LocateSupportProtocol ( + &gEfiAcpiTableProtocolGuid, + gEfiAcpiTableStorageGuid, + &AcpiTable, + FALSE + ); + + ASSERT_EFI_ERROR (Status); + + TableVersion = EFI_ACPI_TABLE_VERSION_2_0; + Table.Signature = EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE; + Status = PlatformUpdateTables ((EFI_ACPI_COMMON_HEADER *)&Table, &TableVersion); + if (!EFI_ERROR (Status)) { + // + // Add SPCR table + // + if (mSpcrTable != NULL) { + DEBUG ((DEBUG_INFO, "mSpcrTable->Header.Length=%d\n", mSpcrTable->Header.Length)); + DEBUG ((DEBUG_INFO, "install=%x\n", &(AcpiTable->InstallAcpiTable))); + DEBUG ((DEBUG_INFO, "acpit=%x\n", AcpiTable)); + DEBUG ((DEBUG_INFO, "mSpcr=%x\n", mSpcrTable)); + DEBUG ((DEBUG_INFO, "len =%d\n", mSpcrTable->Header.Length)); + + TableHandle = 0; + Status = AcpiTable->InstallAcpiTable ( + AcpiTable, + mSpcrTable, + mSpcrTable->Header.Length, + &TableHandle + ); + ASSERT_EFI_ERROR (Status); + } else { + DEBUG ((DEBUG_INFO, "Warning: mSpcrTable is NULL\n")); + } + } + if (mSpcrTable != NULL) { + gBS->FreePool (mSpcrTable); + } + + AcpiEnableAtReadyToBoot(); + + Status = GetOptionData (&gEfiSetupVariableGuid, OFFSET_OF(SYSTEM_CONFIGURATION, ARIForward), &ARIForward, sizeof(UINT8)); + ASSERT_EFI_ERROR (Status); + if (!ARIForward) { + DisableAriForwarding (); + } + +} + + +/** + Installs ACPI Platform tables + + @param None + + @retval EFI_SUCCESS - Operation completed successfully. +**/ +STATIC +EFI_STATUS +EFIAPI +AcpiPlatformEarlyAcpiTablesInstall ( + VOID + ) +{ + EFI_STATUS Status; + EFI_STATUS AcpiStatus; + BOOLEAN Installed; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol; + INTN Instance = 0; + EFI_ACPI_COMMON_HEADER *CurrentTable; + EFI_ACPI_TABLE_VERSION TableVersion; + UINTN TableHandle; + UINT32 FvStatus; + UINT32 Size; + + // + // Find the AcpiTable protocol + // + Status = LocateSupportProtocol ( + &gEfiAcpiTableProtocolGuid, + gEfiAcpiTableStorageGuid, + &AcpiTable, + FALSE + ); + + ASSERT_EFI_ERROR (Status); + + // + // Locate the firmware volume protocol + // + Status = LocateSupportProtocol ( + &gEfiFirmwareVolume2ProtocolGuid, + gEfiAcpiTableStorageGuid, + &FwVol, + TRUE + ); + ASSERT_EFI_ERROR (Status); + + // + // Read tables from the storage file. + // + while (!EFI_ERROR (Status)) { + CurrentTable = NULL; + TableVersion = EFI_ACPI_TABLE_VERSION_NONE; + TableHandle = 0; + Installed = FALSE; + + Status = FwVol->ReadSection ( + FwVol, + &gEfiAcpiTableStorageGuid, + EFI_SECTION_RAW, + Instance, + &CurrentTable, + (UINTN *) &Size, + &FvStatus + ); + + if (!EFI_ERROR (Status)) { + + DEBUG ((DEBUG_INFO, "[ACPI] Table '%c%c%c%c' found in FwVol\n", + ((CHAR8*)&CurrentTable->Signature)[0], ((CHAR8*)&CurrentTable->Signature)[1], + ((CHAR8*)&CurrentTable->Signature)[2], ((CHAR8*)&CurrentTable->Signature)[3])); + + // + // Check if table should be processed or will be updated later + // + if (CurrentTable->Signature != NVDIMM_FW_INTERFACE_TABLE_SIGNATURE + && CurrentTable->Signature != NVDIMM_PLATFORM_CONFIG_ATTRIBUTE_TABLE_SIGNATURE + ) { + // + // Allow platform specific code to reject the table or update it + // + AcpiStatus = AcpiPlatformHooksIsActiveTable (CurrentTable); //SystemBoard); + if (!EFI_ERROR (AcpiStatus)) { + // + // Perform any table specific updates. + // + AcpiStatus = PlatformUpdateTables (CurrentTable, &TableVersion); + if (!EFI_ERROR (AcpiStatus)) { + // + // Add the table + // + if (TableVersion != EFI_ACPI_TABLE_VERSION_NONE) { + // + // Install the table + // + AcpiStatus = AcpiTable->InstallAcpiTable (AcpiTable, CurrentTable, CurrentTable->Length, &TableHandle); + if (!EFI_ERROR (AcpiStatus)) { + Installed = TRUE; + } + ASSERT_EFI_ERROR (AcpiStatus); + } + } + } + } + // + // Increment the instance + // + Instance++; + } + } + + // + // Build any from-scratch ACPI tables. Halt on errors for debug builds, but + // for release builds it is safe to continue. + // + Status = PlatformBuildTables (); + ASSERT_EFI_ERROR (Status); + return EFI_SUCCESS; +} + +/** + Installs ACPI Platform tables that wasn't installed in the early phase + + @param None + + @retval EFI_SUCCESS - Operation completed successfully. +**/ +STATIC +EFI_STATUS +EFIAPI +AcpiPlatformLateAcpiTablesInstall ( + VOID + ) +{ + // + // Install xHCI ACPI Table + // + InstallXhciAcpiTable (); + + return EFI_SUCCESS; +} + + +/** + Installs ACPI PmSsdt tables + + @param None + + @retval EFI_SUCCESS - Operation completed successfully. + +**/ +STATIC +EFI_STATUS +EFIAPI +PmSsdtEarlyAcpiTablesInstall ( + VOID + ) +{ + EFI_STATUS Status; + EFI_STATUS AcpiStatus; + BOOLEAN Installed; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol; + INTN Instance = 0; + EFI_ACPI_COMMON_HEADER *CurrentTable; + EFI_ACPI_TABLE_VERSION TableVersion; + UINTN TableHandle; + UINT32 FvStatus; + UINT32 Size; + + // + // Find the AcpiTable protocol + // + Status = LocateSupportProtocol ( + &gEfiAcpiTableProtocolGuid, + gEfiPmSsdtTableStorageGuid, + &AcpiTable, + FALSE + ); + + ASSERT_EFI_ERROR (Status); + + // + // Locate the firmware volume protocol + // + Status = LocateSupportProtocol ( + &gEfiFirmwareVolume2ProtocolGuid, + gEfiPmSsdtTableStorageGuid, + &FwVol, + TRUE + ); + ASSERT_EFI_ERROR (Status); + + // + // Read tables from the storage file. + // + while (!EFI_ERROR (Status)) { + CurrentTable = NULL; + TableVersion = EFI_ACPI_TABLE_VERSION_NONE; + TableHandle = 0; + Installed = FALSE; + + Status = FwVol->ReadSection ( + FwVol, + &gEfiPmSsdtTableStorageGuid, + EFI_SECTION_RAW, + Instance, + &CurrentTable, + (UINTN *) &Size, + &FvStatus + ); + + if (!EFI_ERROR (Status)) { + // + // Check if table should be processed or will be updated later + // + if (CurrentTable->Signature != NVDIMM_FW_INTERFACE_TABLE_SIGNATURE) { + // + // Allow platform specific code to reject the table or update it + // + AcpiStatus = AcpiPlatformHooksIsActiveTable (CurrentTable); + if (!EFI_ERROR (AcpiStatus)) { + // + // Perform any table specific updates. + // + AcpiStatus = PlatformUpdateTables (CurrentTable, &TableVersion); + if (!EFI_ERROR (AcpiStatus)) { + // + // Add the table + // + if (TableVersion != EFI_ACPI_TABLE_VERSION_NONE) { + // + // Install the table + // + AcpiStatus = AcpiTable->InstallAcpiTable (AcpiTable, CurrentTable, CurrentTable->Length, &TableHandle); + if (!EFI_ERROR (AcpiStatus)) { + Installed = TRUE; + } + ASSERT_EFI_ERROR (AcpiStatus); + } + } + } + } + // + // Increment the instance + // + Instance++; + } + } + return EFI_SUCCESS; +} // PmSsdtEarlyAcpiTablesInstall() + + +/** + Entry point for Acpi platform driver. + + @param ImageHandle - A handle for the image that is initializing this driver. + @param SystemTable - A pointer to the EFI system table. + + @retval EFI_SUCCESS - Driver initialized successfully. + @retval EFI_LOAD_ERROR - Failed to Initialize or has been loaded. + @retval EFI_OUT_OF_RESOURCES - Could not allocate needed resources. +**/ +EFI_STATUS +EFIAPI +AcpiPlatformEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + VOID *HobList; + VOID *RgstPtr; + + DYNAMIC_SI_LIBARY_PROTOCOL *DynamicSiLibraryProtocol = NULL; + + Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &DynamicSiLibraryProtocol); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + mFirstNotify = FALSE; + // + // Report Status Code to indicate Acpi Init + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_BS_ACPI_INIT) + ); + + Status = gBS->LocateProtocol (&gEfiIioUdsProtocolGuid, NULL, &mIioUds2); + if (EFI_ERROR (Status)) { + + ASSERT_EFI_ERROR (Status); + return Status; + } + + mCpuCsrAccessVarPtr = DynamicSiLibraryProtocol->GetSysCpuCsrAccessVar (); + // + // Update HOB variable for PCI resource information + // Get the HOB list. If it is not present, then ASSERT. + // + Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList); + ASSERT_EFI_ERROR (Status); + + // + // Initialize Platform Hooks + // + PlatformHookInit (); + + // + // Install ACPI PLatform Tables + // + Status = AcpiPlatformEarlyAcpiTablesInstall (); + ASSERT_EFI_ERROR (Status); + + // + // Install ACPI PMSsdt Tables + // + Status = PmSsdtEarlyAcpiTablesInstall (); + ASSERT_EFI_ERROR (Status); + + // + // Install ACPI PLatform Tables that wasn't installed yet (NFIT/xHCI) + // + Status = AcpiPlatformLateAcpiTablesInstall (); + ASSERT_EFI_ERROR (Status); + + // + // Register ready to boot event handler + // + Status = EfiCreateEventReadyToBootEx (TPL_NOTIFY, AcpiOnReadyToBootCallback, NULL, &Event); + ASSERT_EFI_ERROR (Status); + + // + // Create PCI Enumeration Completed callback. + // + Event = EfiCreateProtocolNotifyEvent (&gEfiPciEnumerationCompleteProtocolGuid, TPL_CALLBACK, + AcpiOnPciEnumCmplCallback, NULL, &RgstPtr); + ASSERT (Event != NULL); + + // + // Register EndOfDxe handler + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + AcpiOnEndOfDxeCallback, + NULL, + &gEfiEndOfDxeEventGroupGuid, + &Event + ); + ASSERT_EFI_ERROR (Status); + + // + // Register ExitBootServicesEvent handler + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + AcpiOnExitBootServicesCallback, + NULL, + &gEfiEventExitBootServicesGuid, + &Event + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} // AcpiPlatformEntryPoint() diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.h b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.h new file mode 100644 index 0000000000..162c162df8 --- /dev/null +++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.h @@ -0,0 +1,117 @@ +/** @file + + @copyright + Copyright 1999 - 2020 Intel Corporation.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _ACPI_PLATFORM_H_ +#define _ACPI_PLATFORM_H_ + +// +// Statements that include other header files +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Platform.h" +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define RTC_ADDRESS_REGISTER_D 13 + + +/** + Entry point for Acpi platform driver. + + @param ImageHandle - A handle for the image that is initializing this driver. + @param SystemTable - A pointer to the EFI system table. + + @retval EFI_SUCCESS - Driver initialized successfully. + @retval EFI_LOAD_ERROR - Failed to Initialize or has been loaded. + @retval EFI_OUT_OF_RESOURCES - Could not allocate needed resources. +**/ +EFI_STATUS +EFIAPI +AcpiPlatformEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +EFI_STATUS +LocateSupportProtocol ( + IN EFI_GUID *Protocol, + IN EFI_GUID gEfiAcpiMultiTableStorageGuid, + OUT VOID **Instance, + IN UINT32 Type + ); + +VOID +AcpiVtdIntRemappingEnable ( + VOID + ); + +EFI_STATUS +AcpiVtdTablesInstall ( + VOID + ); + +#endif // _ACPI_PLATFORM_H_ diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.inf b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.inf new file mode 100644 index 0000000000..f4980ede74 --- /dev/null +++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.inf @@ -0,0 +1,107 @@ +## @file +# +# @copyright +# Copyright 2009 - 2020 Intel Corporation.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = AcpiPlatform + FILE_GUID = 87AB821C-79B8-4ef6-A913-21D22063F55F + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = AcpiPlatformEntryPoint + +[Sources] + AcpiPlatform.c + AcpiPlatform.h + AcpiPlatformUtils.c + AcpiPlatformUtils.h + AcpiPlatformHooks.c + AcpiPlatformHooks.h + AcpiPlatformVTDHooks.c + +[Packages] + WhitleyOpenBoardPkg/PlatformPkg.dec + WhitleySiliconPkg/SiliconPkg.dec + WhitleySiliconPkg/Cpu/CpuRcPkg.dec + WhitleySiliconPkg/CpRcPkg.dec + WhitleySiliconPkg/WhitleySiliconPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + UefiDriverEntryPoint + BaseMemoryLib + DebugLib + UefiLib + UefiRuntimeServicesTableLib + HobLib + SetupLib + AcpiPlatformTableLib + ReportStatusCodeLib + PcdLib + LocalApicLib + +[Protocols] + gEfiMpServiceProtocolGuid + gEfiIioUdsProtocolGuid + gEfiGlobalNvsAreaProtocolGuid + gEfiPciEnumerationCompleteProtocolGuid + gEfiPciIoProtocolGuid + gEfiFirmwareVolume2ProtocolGuid + gEfiAcpiTableProtocolGuid # ALWAYS_CONSUMED; before was gEfiAcpiSupportProtocolGuid + gEfiSerialIoProtocolGuid + gDxeEnhancedSpeedstepProtocolGuid + gEfiPlatformTypeProtocolGuid + gDmaRemapProtocolGuid + gEfiCrystalRidgeGuid + gEfiSmbiosProtocolGuid + gEfiPciRootBridgeIoProtocolGuid + gAcpiPlatformProtocolGuid + gDynamicSiLibraryProtocolGuid ## CONSUMES + gDynamicSiLibraryProtocol2Guid ## CONSUMES + +[Guids] + gEfiGlobalVariableGuid + gEfiAcpiTableStorageGuid + gEfiPmSsdtTableStorageGuid + gEfiPcAnsiGuid + gEfiVT100PlusGuid + gEfiVT100Guid + gEfiVTUTF8Guid + gEfiHobListGuid + gEfiPlatformInfoGuid + gEfiSetupVariableGuid + gEfiEndOfDxeEventGroupGuid + gEfiEventExitBootServicesGuid + gEfiSocketIioVariableGuid + gEfiSocketMemoryVariableGuid + gEfiSocketCommonRcVariableGuid + gEfiSocketMpLinkVariableGuid + gEfiSocketPowermanagementVarGuid + gEfiSocketProcessorCoreVarGuid + gPchInfoHobGuid ## CONSUMES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId + gOemSkuTokenSpaceGuid.PcdOemTableIdXhci + gPlatformTokenSpaceGuid.PcdDebugModeEnable ## CONSUMES + +[FixedPcd] + gEfiCpRcPkgTokenSpaceGuid.PcdMaxCpuSocketCount + gEfiCpRcPkgTokenSpaceGuid.PcdMaxCpuCoreCount + +[Depex] + gDynamicSiLibraryProtocolGuid AND + gDynamicSiLibraryProtocol2Guid AND + gDmaRemapProtocolGuid AND + gEfiAcpiTableProtocolGuid AND + gEfiMpServiceProtocolGuid AND + gEfiIioSystemProtocolGuid AND + gSmbiosMemInfoProtocolGuid diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformHooks.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformHooks.c new file mode 100644 index 0000000000..93f312a178 --- /dev/null +++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformHooks.c @@ -0,0 +1,384 @@ +/** @file + ACPI Platform Driver Hooks + + @copyright + Copyright 1996 - 2020 Intel Corporation.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +// +// Statements that include other files +// +#include "AcpiPlatform.h" +#include "AcpiPlatformUtils.h" +#include "AcpiPlatformHooks.h" + +#ifndef __GNUC__ +#pragma optimize("",off) +#endif //__GNUC__ + +extern BOOLEAN mX2ApicEnabled; +extern UINT32 mNumOfBitShift; +extern EFI_PLATFORM_INFO *mPlatformInfo; +extern BIOS_ACPI_PARAM *mAcpiParameter; +extern EFI_IIO_UDS_PROTOCOL *mIioUds2; +extern CPU_CSR_ACCESS_VAR *mCpuCsrAccessVarPtr; + +extern SOCKET_MEMORY_CONFIGURATION mSocketMemoryConfiguration; +extern SOCKET_MP_LINK_CONFIGURATION mSocketMpLinkConfiguration; +extern SOCKET_COMMONRC_CONFIGURATION mSocketCommonRcConfiguration; +extern SOCKET_IIO_CONFIGURATION mSocketIioConfiguration; + +extern SOCKET_POWERMANAGEMENT_CONFIGURATION mSocketPowermanagementConfiguration; +extern SOCKET_PROCESSORCORE_CONFIGURATION mSocketProcessorCoreConfiguration; + +extern SYSTEM_CONFIGURATION mSystemConfiguration; +extern PCH_SETUP mPchSetup; +extern BOOLEAN Is14nmCpu; + +EFI_GLOBAL_NVS_AREA_PROTOCOL mGlobalNvsArea; + + +EFI_STATUS +PlatformHookInit ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_PHYSICAL_ADDRESS AcpiParameterAddr; + EFI_CPUID_REGISTER CpuidRegisters; + SETUP_DATA SetupData; + + ASSERT (mIioUds2); + + Status = EFI_SUCCESS; + + Status = GetEntireConfig (&SetupData); + + CopyMem (&mSocketMemoryConfiguration, &(SetupData.SocketConfig.MemoryConfig), sizeof(SOCKET_MEMORY_CONFIGURATION)); + CopyMem (&mSocketMpLinkConfiguration, &(SetupData.SocketConfig.UpiConfig), sizeof(SOCKET_MP_LINK_CONFIGURATION)); + CopyMem (&mSocketCommonRcConfiguration, &(SetupData.SocketConfig.CommonRcConfig), sizeof(SOCKET_COMMONRC_CONFIGURATION)); + CopyMem (&mSocketPowermanagementConfiguration, &(SetupData.SocketConfig.PowerManagementConfig), sizeof(SOCKET_POWERMANAGEMENT_CONFIGURATION)); + CopyMem (&mSocketProcessorCoreConfiguration, &(SetupData.SocketConfig.SocketProcessorCoreConfiguration), sizeof(SOCKET_PROCESSORCORE_CONFIGURATION)); + CopyMem (&mSystemConfiguration, &(SetupData.SystemConfig), sizeof(SYSTEM_CONFIGURATION)); + CopyMem (&mSocketIioConfiguration, &(SetupData.SocketConfig.IioConfig), sizeof(SOCKET_IIO_CONFIGURATION)); + CopyMem (&mPchSetup, &(SetupData.PchSetup), sizeof(PCH_SETUP)); + + if (EFI_ERROR (Status)) { + mSocketPowermanagementConfiguration.ProcessorEistEnable = 0; + mSocketPowermanagementConfiguration.TurboMode = 0; + mSocketPowermanagementConfiguration.PackageCState = 0; + mSocketPowermanagementConfiguration.PwrPerfTuning = PWR_PERF_TUNING_BIOS_CONTROL; + mSocketProcessorCoreConfiguration.ProcessorX2apic = 0; + mSocketProcessorCoreConfiguration.ForcePhysicalModeEnable = 0; + } + // + // If Emulation flag set by InitializeDefaultData in ProcMemInit.c + // force X2APIC + // Else read setup data + // + mX2ApicEnabled = mSocketProcessorCoreConfiguration.ProcessorX2apic; + + // + // Force x2APIC if the system is configured as X2APIC; or CPU hotplug is enabled. + // + if ((GetApicMode () == LOCAL_APIC_MODE_X2APIC) || (mIioUds2->IioUdsPtr->SystemStatus.OutKtiCpuSktHotPlugEn)) { + mX2ApicEnabled = TRUE; + } + + // + // Allocate 256 runtime memory to pass ACPI parameter + // This Address must be < 4G because we only have 32bit in the dsdt + // + AcpiParameterAddr = 0xffffffff; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIMemoryNVS, + EFI_SIZE_TO_PAGES (sizeof(BIOS_ACPI_PARAM)), + &AcpiParameterAddr + ); + ASSERT_EFI_ERROR (Status); + mAcpiParameter = (BIOS_ACPI_PARAM *)AcpiParameterAddr; + + DEBUG ((DEBUG_INFO, "ACPI Parameter Block Address: 0x%X\n", mAcpiParameter)); + + ZeroMem (mAcpiParameter, sizeof (BIOS_ACPI_PARAM)); + mAcpiParameter->PlatformId = (UINT32)mPlatformInfo->BoardId; + mAcpiParameter->IoApicEnable = mPlatformInfo->SysData.SysIoApicEnable; + mAcpiParameter->PchIoApic_24_119 = mPchSetup.PchIoApic24119Entries; + + Handle = NULL; + mGlobalNvsArea.Area = mAcpiParameter; + gBS->InstallProtocolInterface ( + &Handle, + &gEfiGlobalNvsAreaProtocolGuid, + EFI_NATIVE_INTERFACE, + &mGlobalNvsArea + ); + ASSERT_EFI_ERROR (Status); + + AsmCpuid (CPUID_VERSION_INFO, &CpuidRegisters.RegEax, &CpuidRegisters.RegEbx, &CpuidRegisters.RegEcx, &CpuidRegisters.RegEdx); + mAcpiParameter->ProcessorId = (CpuidRegisters.RegEax & 0xFFFF0); + + // + // support up to 64 threads/socket + // + AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 1, &mNumOfBitShift, NULL, NULL, NULL); + mNumOfBitShift &= 0x1F; + + // + // Set the bit shift value for CPU SKU + // + mAcpiParameter->CpuSkuNumOfBitShift = (UINT8) mNumOfBitShift; + + mAcpiParameter->ProcessorApicIdBase[0] = (UINT32) (0 << mNumOfBitShift); + mAcpiParameter->ProcessorApicIdBase[1] = (UINT32) (1 << mNumOfBitShift); + mAcpiParameter->ProcessorApicIdBase[2] = (UINT32) (2 << mNumOfBitShift); + mAcpiParameter->ProcessorApicIdBase[3] = (UINT32) (3 << mNumOfBitShift); + mAcpiParameter->ProcessorApicIdBase[4] = (UINT32) (4 << mNumOfBitShift); + mAcpiParameter->ProcessorApicIdBase[5] = (UINT32) (5 << mNumOfBitShift); + mAcpiParameter->ProcessorApicIdBase[6] = (UINT32) (6 << mNumOfBitShift); + mAcpiParameter->ProcessorApicIdBase[7] = (UINT32) (7 << mNumOfBitShift); + + // + // If SNC is enabled, and NumOfCluster is 2, set the ACPI variable for PXM value + // + if (mIioUds2->IioUdsPtr->SystemStatus.OutSncEn) { + mAcpiParameter->SncAnd2Cluster = mIioUds2->IioUdsPtr->SystemStatus.OutNumOfCluster; + } + + mAcpiParameter->MmCfg = (UINT32)mIioUds2->IioUdsPtr->PlatformData.PciExpressBase; + mAcpiParameter->TsegSize = (UINT32)(mIioUds2->IioUdsPtr->PlatformData.MemTsegSize >> 20); + + Status = PlatformHookAfterAcpiParamInit (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "PlatformHookAfterAcpiParamInit() failed with Status: %r\n", Status)); + } + + return Status; +} + + +/** + Install and patch specific ACPI Table + + @param AcpiTableSignature + + @retval None +**/ +VOID +InstallAndPatchAcpiTable ( + UINT32 AcpiTableSignature + ) +{ + EFI_STATUS Status; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + EFI_ACPI_TABLE_VERSION TableVersion; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol; + EFI_ACPI_COMMON_HEADER *CurrentTable = NULL; + UINT32 FvStatus; + UINTN Size; + UINTN TableHandle = 0; + INTN Instance = 0; + + DEBUG ((DEBUG_INFO, "InstallAndPatchAcpiTable '%c%c%c%c'\n", + ((CHAR8*)&AcpiTableSignature)[0], ((CHAR8*)&AcpiTableSignature)[1], + ((CHAR8*)&AcpiTableSignature)[2], ((CHAR8*)&AcpiTableSignature)[3])); + + Status = LocateSupportProtocol ( + &gEfiAcpiTableProtocolGuid, + gEfiAcpiTableStorageGuid, + &AcpiTable, + FALSE + ); + ASSERT_EFI_ERROR (Status); + + Status = LocateSupportProtocol ( + &gEfiFirmwareVolume2ProtocolGuid, + gEfiAcpiTableStorageGuid, + &FwVol, + TRUE + ); + ASSERT_EFI_ERROR (Status); + + while (!EFI_ERROR (Status)) { + + Status = FwVol->ReadSection ( + FwVol, + &gEfiAcpiTableStorageGuid, + EFI_SECTION_RAW, + Instance, + &CurrentTable, + (UINTN *) &Size, + &FvStatus + ); + + if (!EFI_ERROR (Status)) { + if (CurrentTable->Signature == AcpiTableSignature) { + + Status = AcpiPlatformHooksIsActiveTable (CurrentTable); + if (!EFI_ERROR (Status)) { + + Status = PlatformUpdateTables (CurrentTable, &TableVersion); + if (!EFI_ERROR (Status)) { + + if (TableVersion != EFI_ACPI_TABLE_VERSION_NONE) { + Status = AcpiTable->InstallAcpiTable ( + AcpiTable, + CurrentTable, + CurrentTable->Length, + &TableHandle + ); + } + } + ASSERT_EFI_ERROR (Status); + } else { + DEBUG ((DEBUG_ERROR, "No Table for current platform\n")); + } + } + + CurrentTable = NULL; + Instance++; + } + } +} + + +/** + Install Xhci ACPI Table + +**/ +VOID +InstallXhciAcpiTable ( + VOID + ) +{ + EFI_HANDLE *HandleBuffer; + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol; + EFI_ACPI_COMMON_HEADER *CurrentTable; + UINT32 FvStatus; + UINTN Size; + UINTN TableHandle; + INTN Instance; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + EFI_ACPI_DESCRIPTION_HEADER *TableHeader; + UINT64 XhciAcpiTable; + UINT64 *XhciAcpiTablePtr; + UINT64 TempOemTableId; + + HandleBuffer = 0; + Instance = 0; + TableHandle = 0; + CurrentTable = NULL; + FwVol = NULL; + XhciAcpiTable = 0; + + DEBUG ((DEBUG_INFO, "InstallXhciAcpiTable\n")); + + + XhciAcpiTablePtr = (UINT64*)PcdGetPtr (PcdOemTableIdXhci); + if (XhciAcpiTablePtr == NULL) { + DEBUG ((DEBUG_ERROR, "XhciAcpiTablePtr is NULL\n")); + ASSERT (XhciAcpiTablePtr != NULL); + return; + } + + XhciAcpiTable = *XhciAcpiTablePtr; + + // + // Find the AcpiSupport protocol + // + Status = LocateSupportProtocol ( + &gEfiAcpiTableProtocolGuid, + gEfiAcpiTableStorageGuid, + &AcpiTable, + FALSE + ); + + ASSERT_EFI_ERROR (Status); + + // + // Locate the firmware volume protocol + // + Status = LocateSupportProtocol ( + &gEfiFirmwareVolume2ProtocolGuid, + gEfiAcpiTableStorageGuid, + &FwVol, + TRUE + ); + + ASSERT_EFI_ERROR (Status); + + // + // Read tables from the storage file. + // + while (Status == EFI_SUCCESS) { + Status = FwVol->ReadSection ( + FwVol, + &gEfiAcpiTableStorageGuid, + EFI_SECTION_RAW, + Instance, + &CurrentTable, + &Size, + &FvStatus + ); + + if (!EFI_ERROR (Status)) { + + TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable; + + if (TableHeader->OemTableId == XhciAcpiTable) { + DEBUG ((DEBUG_INFO, "Install xhci table: %x\n", TableHeader->OemTableId)); + + TempOemTableId = PcdGet64 (PcdAcpiDefaultOemTableId); + + CopyMem (TableHeader->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof(TableHeader->OemId)); + CopyMem (&TableHeader->OemTableId, &TempOemTableId, sizeof(TableHeader->OemTableId)); + + TableHeader->CreatorId = EFI_ACPI_CREATOR_ID; + TableHeader->CreatorRevision = EFI_ACPI_CREATOR_REVISION; + + // + // Add the table + // + TableHandle = 0; + + Status = AcpiTable->InstallAcpiTable ( + AcpiTable, + CurrentTable, + CurrentTable->Length, + &TableHandle + ); + break; + } + + // + // Increment the instance + // + + Instance++; + CurrentTable = NULL; + } + } +} + +UINT8 +EFIAPI +DetectHwpFeature ( + VOID + ) +{ + EFI_STATUS Status; + DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL; + + Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return FALSE; + } + + return DynamicSiLibraryProtocol2->DetectHwpFeature (); +} diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformHooks.h b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformHooks.h new file mode 100644 index 0000000000..2201dd5316 --- /dev/null +++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformHooks.h @@ -0,0 +1,51 @@ +/** @file + + @copyright + Copyright 1996 - 2020 Intel Corporation.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _ACPI_PLATFORM_HOOKS_H_ +#define _ACPI_PLATFORM_HOOKS_H_ + +// +// Statements that include other header files +// +#include +#include +#include +#include + +EFI_STATUS +PlatformHookInit ( + VOID + ); + +VOID +DisableAriForwarding ( + VOID + ); + +EFI_STATUS +AllocateRasfSharedMemory ( + VOID + ); + +UINT8 +EFIAPI +DetectHwpFeature ( + VOID + ); + +VOID +InstallAndPatchAcpiTable ( + UINT32 + ); + +VOID +InstallXhciAcpiTable ( + VOID + ); + +#endif diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformUtils.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformUtils.c new file mode 100644 index 0000000000..27a9803fcc --- /dev/null +++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformUtils.c @@ -0,0 +1,133 @@ +/** @file + ACPI Platform Utilities + + @copyright + Copyright 2017 - 2018 Intel Corporation.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "AcpiPlatformUtils.h" +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Locate the first instance of a protocol. If the protocol requested is an + FV protocol, then it will return the first FV that contains the ACPI table + storage file. + + @param[in] Protocol - The protocol to find. + @param[in] EfiAcpiStorageGuid - EFI ACPI tables storage guid + @param[out] Instance - Return pointer to the first instance of the protocol. + @param[in] Type - The type of protocol to locate. + + @retval EFI_SUCCESS - The function completed successfully. + @retval EFI_NOT_FOUND - The protocol could not be located. + @retval EFI_OUT_OF_RESOURCES - There are not enough resources to find the protocol. +**/ +EFI_STATUS +LocateSupportProtocol ( + IN EFI_GUID *Protocol, + IN EFI_GUID EfiAcpiStorageGuid, + OUT VOID **Instance, + IN UINT32 Type + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN NumberOfHandles; + EFI_FV_FILETYPE FileType; + UINT32 FvStatus; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINTN Size; + UINTN Index; + + FvStatus = 0; + // + // Locate protocol. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + Protocol, + NULL, + &NumberOfHandles, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + // + // Defined errors at this time are not found and out of resources. + // + return Status; + } + // + // Looking for FV with ACPI storage file + // + for (Index = 0; Index < NumberOfHandles; Index++) { + // + // Get the protocol on this handle + // This should not fail because of LocateHandleBuffer + // + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + Protocol, + Instance + ); + ASSERT (!EFI_ERROR (Status)); + + if (!Type) { + // + // Not looking for the FV protocol, so find the first instance of the + // protocol. There should not be any errors because our handle buffer + // should always contain at least one or LocateHandleBuffer would have + // returned not found. + // + break; + } + // + // See if it has the ACPI storage file + // + Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL *) (*Instance))->ReadFile ( + *Instance, + &EfiAcpiStorageGuid, + NULL, + &Size, + &FileType, + &Attributes, + &FvStatus + ); + + // + // If we found it, then we are done + // + if (!EFI_ERROR (Status)) { + break; + } + } + // + // Our exit status is determined by the success of the previous operations + // If the protocol was found, Instance already points to it. + // + // + // Free any allocated buffers + // + gBS->FreePool (HandleBuffer); + + return Status; +} diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformUtils.h b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformUtils.h new file mode 100644 index 0000000000..50a5f0471e --- /dev/null +++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformUtils.h @@ -0,0 +1,66 @@ +/** @file + + @copyright + Copyright 2017 - 2018 Intel Corporation.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _ACPI_PLATFORM_UTILS_H_ +#define _ACPI_PLATFORM_UTILS_H_ + +extern EFI_GUID gEfiAcpiTableStorageGuid; + + +/** + Function checks if ACPI Platform Protocol is ready to install + + @param None + + @retval TRUE ACPI Platform Protocol can be installed, + FALSE ACPI Platform Protocol not ready yet + +**/ +BOOLEAN +IsAcpiPlatformProtocolReadyForInstall ( + VOID + ); + +/** + Function checks if ACPI Platform Protocol is already installed + + @param None + + @retval TRUE ACPI Platform Protocol is installed, + FALSE ACPI Platform Protocol not installed yet + +**/ +BOOLEAN +IsAcpiPlatformProtocolInstalled ( + VOID + ); + +/** + Locate the first instance of a protocol. If the protocol requested is an + FV protocol, then it will return the first FV that contains the ACPI table + storage file. + + @param[in] Protocol - The protocol to find. + @param[in] EfiAcpiStorageGuid - EFI ACPI tables storage guid + @param[out] Instance - Return pointer to the first instance of the protocol. + @param[in] Type - The type of protocol to locate. + + @retval EFI_SUCCESS - The function completed successfully. + @retval EFI_NOT_FOUND - The protocol could not be located. + @retval EFI_OUT_OF_RESOURCES - There are not enough resources to find the protocol. + +**/ +EFI_STATUS +LocateSupportProtocol ( + IN EFI_GUID *Protocol, + IN EFI_GUID EfiAcpiStorageGuid, + OUT VOID **Instance, + IN UINT32 Type + ); + +#endif // _ACPI_PLATFORM_UTILS_H_ diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformVTDHooks.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformVTDHooks.c new file mode 100644 index 0000000000..a517a9adce --- /dev/null +++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformVTDHooks.c @@ -0,0 +1,1762 @@ +/** @file + ACPI Platform Driver VT-D Hooks + + @copyright + Copyright 2012 - 2021 Intel Corporation.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "AcpiPlatform.h" +#include "AcpiPlatformHooks.h" +#include +#include +#include +#include + +extern EFI_PLATFORM_INFO *mPlatformInfo; +extern BIOS_ACPI_PARAM *mAcpiParameter; +extern EFI_IIO_UDS_PROTOCOL *mIioUds2; +extern CPU_CSR_ACCESS_VAR *mCpuCsrAccessVarPtr; +extern SYSTEM_CONFIGURATION mSystemConfiguration; +extern SOCKET_IIO_CONFIGURATION mSocketIioConfiguration; +extern SOCKET_PROCESSORCORE_CONFIGURATION mSocketProcessorCoreConfiguration; +extern EFI_GUID mSystemConfigurationGuid; +extern BOOLEAN mX2ApicEnabled; + + +#define EFI_PCI_CAPABILITY_PTR 0x34 +#define EFI_PCIE_CAPABILITY_BASE_OFFSET 0x100 +#define EFI_PCIE_CAPABILITY_ID_ACS 0x000D +#define EFI_PCI_CAPABILITY_ID_PCIEXP 0x10 +#define EFI_PCI_EXPRESS_CAPABILITY_REGISTER 0x02 + +#define ACS_CAPABILITY_REGISTER 0x04 +#define ACS_SOURCE_VALIDATION BIT0 +#define ACS_P2P_REQUEST_REDIRECT BIT2 +#define ACS_P2P_COMPLETION_REDIRECT BIT3 +#define ACS_UPSTREAM_FORWARDING BIT4 + +#define ACS_CONTROL_REGISTER 0x06 +#define ACS_SOURCE_VALIDATION_ENABLE BIT0 +#define ACS_P2P_REQUEST_REDIRECT_ENABLE BIT2 +#define ACS_P2P_COMPLETION_REDIRECT_ENABLE BIT3 +#define ACS_UPSTREAM_FORWARDING_ENABLE BIT4 + +#define R_VTD_GCMD_REG 0x18 +#define R_VTD_GSTS_REG 0x1C +#define R_VTD_IQT_REG 0x88 +#define R_VTD_IQA_REG 0x90 +#define R_VTD_IRTA_REG 0xB8 + +#define VTD_ISOCH_ENGINE_OFFSET 0x1000 + +// +// a flag to indicate if we should disable Vt-d for ACS WA +// +BOOLEAN mDisableVtd = FALSE; + +DMA_REMAP_PROTOCOL DmaRemapProt; +#define VTD_SUPPORT_INSTANCE_FROM_THIS(a) CR(a, VTD_SUPPORT_INSTANCE, DmaRemapProt, EFI_ACPI_6_2_DMA_REMAPPING_TABLE_SIGNATURE) +#define EFI_PCI_CAPABILITY_ID_ATS 0x0F + +#define SEGMENT0 0x00 +#define MEM_BLK_COUNT 0x140 +#define INTRREMAP BIT3 +#define MEMORY_SIZE (MaxIIO * NUMBER_PORTS_PER_SOCKET) +#define R_VTD_EXT_CAP_LOW 0x10 +#define R_VTD_EXT_CAP_HIGH 0x14 +#define IIO_STACK0 0 +#define IOAT_DEVICE_NUM_10NM 0x01 + + +PCI_NODE mPciPath0_1[] = { + {PCI_DEVICE_NUMBER_PCH_HDA, PCI_FUNCTION_NUMBER_PCH_HDA}, + {(UINT8) -1, (UINT8) -1}, +}; + +// +// IOAPIC2 - IIO IoApic +// +PCI_NODE mPciPath2_0_10nm[] = { + { PCIE_PORT_0_DEV_0, PCIE_PORT_0_FUNC_0 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_1_10nm[] = { + { PCIE_PORT_1A_DEV_1, PCIE_PORT_1A_FUNC_1 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_2_10nm[] = { + { PCIE_PORT_1B_DEV_1, PCIE_PORT_1B_FUNC_1 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_3_10nm[] = { + { PCIE_PORT_1C_DEV_1, PCIE_PORT_1C_FUNC_1 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_4_10nm[] = { + { PCIE_PORT_1D_DEV_1, PCIE_PORT_1D_FUNC_1 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_5_10nm[] = { + { PCIE_PORT_2A_DEV_2, PCIE_PORT_2A_FUNC_2 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_6_10nm[] = { + { PCIE_PORT_2B_DEV_2, PCIE_PORT_2B_FUNC_2 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_7_10nm[] = { + { PCIE_PORT_2C_DEV_2, PCIE_PORT_2C_FUNC_2 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_8_10nm[] = { + { PCIE_PORT_2D_DEV_2, PCIE_PORT_2D_FUNC_2 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_9_10nm[] = { + { PCIE_PORT_3A_DEV_3, PCIE_PORT_3A_FUNC_3 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_10_10nm[] = { + { PCIE_PORT_3B_DEV_3, PCIE_PORT_3B_FUNC_3 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_11_10nm[] = { + { PCIE_PORT_3C_DEV_3, PCIE_PORT_3C_FUNC_3 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_12_10nm[] = { + { PCIE_PORT_3D_DEV_3, PCIE_PORT_3D_FUNC_3 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_13_10nm[] = { + { PCIE_PORT_4A_DEV_4, PCIE_PORT_4A_FUNC_4 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_14_10nm[] = { + { PCIE_PORT_4B_DEV_4, PCIE_PORT_4B_FUNC_4 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_15_10nm[] = { + { PCIE_PORT_4C_DEV_4, PCIE_PORT_4C_FUNC_4 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_16_10nm[] = { + { PCIE_PORT_4D_DEV_4, PCIE_PORT_4D_FUNC_4 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_17_10nm[] = { + { PCIE_PORT_5A_DEV_5, PCIE_PORT_5A_FUNC_5 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_18_10nm[] = { + { PCIE_PORT_5B_DEV_5, PCIE_PORT_5B_FUNC_5 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_19_10nm[] = { + { PCIE_PORT_5C_DEV_5, PCIE_PORT_5C_FUNC_5 }, + { (UINT8)-1, (UINT8)-1 }, +}; +PCI_NODE mPciPath2_20_10nm[] = { + { PCIE_PORT_5D_DEV_5, PCIE_PORT_5D_FUNC_5 }, + { (UINT8)-1, (UINT8)-1 }, +}; + +DEVICE_SCOPE mDevScopeDRHD[] = { + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT, // Device type - HD Audio + 00, // Enumeration ID + DEFAULT_PCI_BUS_NUMBER_PCH, // Start Bus Number + &mPciPath0_1[0] + }, +}; + +DEVICE_SCOPE mDevScopeATSR10nm[] = { + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port1 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_0_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port2 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_1_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port3 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_2_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port4 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_3_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port5 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_4_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port6 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_5_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port7 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_6_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port8 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_7_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port9 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_8_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port10 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_9_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port11 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_10_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port12 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_11_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port13 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_12_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port14 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_13_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port15 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_14_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port16 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_15_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port17 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_16_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port18 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_17_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port19 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_18_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port20 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_19_10nm[0] + }, + { + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port21 + 00, // Enumeration ID + DMI_BUS_NUM, + &mPciPath2_20_10nm[0] + } +}; + +DMAR_DRHD mDrhd = { + DRHD_SIGNATURE, + 00, // Flags + SEGMENT0, // Segment number + 00, // Base Address + 00, // Number of dev scope structures + &mDevScopeDRHD[0] +}; + +DMAR_DRHD mDrhdIsoc = { + DRHD_SIGNATURE, + 00, // Flags + SEGMENT0, // Segment number + 00, // Base Address + 00, // Number of dev scope structures + &mDevScopeDRHD[0] +}; + +DMAR_ATSR mAtsr10nm = { + ATSR_SIGNATURE, + SEGMENT0, // Segment number + 00, + NUMBER_PORTS_PER_SOCKET - 1, + 00, + &mDevScopeATSR10nm[0] +}; + +PCI_NODE mPciPath[] = { + { 00, 00}, + { (UINT8)-1, (UINT8)-1}, +}; + +UINT8 IoApicID[] = { PCH_IOAPIC_ID, //PCH + PC00_IOAPIC_ID, PC01_IOAPIC_ID, PC02_IOAPIC_ID, PC03_IOAPIC_ID, PC04_IOAPIC_ID, PC05_IOAPIC_ID, //Socket0 + PC06_IOAPIC_ID, PC07_IOAPIC_ID, PC08_IOAPIC_ID, PC09_IOAPIC_ID, PC10_IOAPIC_ID, PC11_IOAPIC_ID, //Socket1 + PC12_IOAPIC_ID, PC13_IOAPIC_ID, PC14_IOAPIC_ID, PC15_IOAPIC_ID, PC16_IOAPIC_ID, PC17_IOAPIC_ID, //Socket2 + PC18_IOAPIC_ID, PC19_IOAPIC_ID, PC20_IOAPIC_ID, PC21_IOAPIC_ID, PC22_IOAPIC_ID, PC23_IOAPIC_ID, //Socket3 + PC24_IOAPIC_ID, PC25_IOAPIC_ID, PC26_IOAPIC_ID, PC27_IOAPIC_ID, PC28_IOAPIC_ID, PC29_IOAPIC_ID, //Socket4 + PC30_IOAPIC_ID, PC31_IOAPIC_ID, PC32_IOAPIC_ID, PC33_IOAPIC_ID, PC34_IOAPIC_ID, PC35_IOAPIC_ID, //Socket5 + PC36_IOAPIC_ID, PC37_IOAPIC_ID, PC38_IOAPIC_ID, PC39_IOAPIC_ID, PC40_IOAPIC_ID, PC41_IOAPIC_ID, //Socket6 + PC42_IOAPIC_ID, PC43_IOAPIC_ID, PC44_IOAPIC_ID, PC45_IOAPIC_ID, PC46_IOAPIC_ID, PC47_IOAPIC_ID, //Socket7 +}; + +PCI_NODE mPciPath7[] = { + { PCI_DEVICE_NUMBER_PCH_XHCI, PCI_FUNCTION_NUMBER_PCH_XHCI }, + { (UINT8)-1, (UINT8)-1}, +}; +DEVICE_SCOPE DevScopeRmrr[] = { + { + 1, // RMRR dev Scope - XHCI + 0, // Enumeration ID + 0, // Start Bus Number + &mPciPath7[0] + }, +}; + +DMAR_RMRR mRmrr = { + RMRR_SIGNATURE, // Signature + SEGMENT0, // Segment number + ' ', // Reserved Memory RegionBase Address + ' ', // Reserved Memory RegionLimit Address + ' ', // Number of Dev Scope structures + &DevScopeRmrr[0] +}; + +typedef struct { + UINT8 aBuf[32]; +} MEM_BLK; + +DMAR_RHSA mRhsa; + +typedef struct { + UINT8 Bus; + UINT8 Dev; + UINT8 Func; +} DMAR_DEVICE; + +EFI_STATUS +LocateCapRegBlock( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT8 CapID, + OUT UINT8 *PciExpressOffset, + OUT UINT8 *NextRegBlock + ); + +EFI_STATUS +LocatePciExpressCapRegBlock ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 CapID, + OUT UINT32 *Offset, + OUT UINT32 *NextRegBlock +); + +DMAR_DRHD mDrhd; +DMAR_RHSA mRhsa; + +DMAR_ATSR* GetDmarAtsrTablePointer ( + VOID + ) +{ + DMAR_ATSR* pAtsr = NULL; + + pAtsr = &mAtsr10nm; + + return pAtsr; +} + + +/** + Enable VT-d interrupt remapping. + + This function should be called late at ReadyToBoot event. If called in AcpiVtdTablesInstall() + would hang in CpuDeadLoop() because of timeout when waiting for invalidation commands complete. +**/ +VOID +AcpiVtdIntRemappingEnable ( + VOID + ) +{ + EFI_STATUS Status; + UINT64 *xApicAddr; + UINT64 *IRTA; + UINT64 *Addr; + UINT64 Value=0; + UINT16 IRTECount; + UINT16 Count; + UINT64 IRTEValue; + UINT8 RemapEng; + UINT8 RemapEngCount; + EFI_CPUID_REGISTER CpuidRegisters; + UINT32 VtdBarAddress; + UINT8 Stack; + VTD_SUPPORT_INSTANCE *DmarPrivateData; + DMA_REMAP_PROTOCOL *DmaRemap = NULL; + + static volatile UINT64 TempQWord[MaxIIO] = {0}; + + DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL; + + Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return; + } + + Status = gBS->LocateProtocol (&gDmaRemapProtocolGuid, NULL, &DmaRemap); + if (EFI_ERROR (Status) || !DmaRemap->VTdSupport || !DmaRemap->InterruptRemap) { + + DEBUG ((DEBUG_INFO, "[VTD] %a disabled\n", + (DmaRemap != NULL && DmaRemap->VTdSupport) ? "Interrupt remapping" : "Virtualization Technology for Directed I/O")); + return; + } + ASSERT (mIioUds2); + + IRTEValue = 00; + RemapEng = 0; + RemapEngCount = mIioUds2->IioUdsPtr->PlatformData.numofIIO; + DmarPrivateData = VTD_SUPPORT_INSTANCE_FROM_THIS (DmaRemap); + + if (RemapEngCount > NELEMENTS (TempQWord)) { + DEBUG ((DEBUG_ERROR, "[ACPI](DMAR) ERROR: Number of IIO exceed internal table (%d > %d)\n", RemapEngCount, NELEMENTS (TempQWord))); + RemapEngCount = NELEMENTS (TempQWord); + } + + // + // Xapic tables update + // + IRTECount = 16 * 24; // Total 24 IRTE entries with 128 bits each. + // + // Allocate 4K alligned space for IRTE entries Added extra space of 500 bytes. + // + Status = gBS->AllocatePool (EfiACPIReclaimMemory, IRTECount + 0x1500, &xApicAddr); + ASSERT_EFI_ERROR (Status); + + // + // Allocate IRT - Allocate zero-initialized, 4KB aligned, 4KB memory for interrupt-remap-table and mark this memory as "ACPI Reclaim Memory" + // + xApicAddr = (UINT64 *)((UINT64)xApicAddr & (~0xFFF)); + ZeroMem (xApicAddr, IRTECount +0x1500); + + // + // 1. Program IRTE - Initialize the interrupt-remap-table as follows: (this table will be shared by all VT-d units) + // + for (Count = 0; Count < 24; Count++) { + + IRTEValue = 00; + if (Count == 0) { + IRTEValue = (7 << 05) + 03; // Preset flag set, Ext int enabled, FPD set + } + + AsmCpuid ( + CPUID_EXTENDED_TOPOLOGY, + &CpuidRegisters.RegEax, + &CpuidRegisters.RegEbx, + &CpuidRegisters.RegEcx, + &CpuidRegisters.RegEdx + ); + IRTEValue |= (UINT64)CpuidRegisters.RegEdx << 32; // Destination Processor Apic ID + + *(volatile UINT64 *)((UINT64)xApicAddr + (Count * 16))= IRTEValue; + + // + // Perform a CLFLUSH instruction for each cachline in this 4KB memory to ensure that updates to the interrupt-remap-table are visible in memory + // + AsmFlushCacheLine ((VOID *)((UINT64)xApicAddr + (Count * 16))); + } + // + // 3. Program the VT-D remap engines + // + for (RemapEng = 0; RemapEng < RemapEngCount; RemapEng++) { + for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) { + // + // Check for valid stack + // + if (!(mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[RemapEng].stackPresentBitmap & (1 << Stack))) { + continue; + } + VtdBarAddress = DynamicSiLibraryProtocol2->GetVtdBar (RemapEng, Stack); + if (VtdBarAddress) { + // + // 2. For each VT-d unit in the platform, allocate and initialize the invalidation queue/commands as follows + // + + // + // Allocate memory for the queued invalidation. + // + Status = gBS->AllocatePool (EfiACPIReclaimMemory, 0x1000 + 0x1000, &Addr); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + return; + } + ZeroMem (Addr, 0x1000 + 0x1000); + Addr = (UINT64 *)((UINT64)Addr & (~0xFFF)); + + // + // Submit two descriptors to the respective VT-d unit's invalidation queue as follows: + // Program 1st descriptor in invalidation-queue as Interrupt-Entry-Cache Invalidation Descriptor + // with G (Granularity) field Clear + // + Addr[0] = 0x04; // Interrupt Entry Cache Invalidate Descriptor + Addr[1] = 0x00; + + // + // Program 2nd descriptor in invalidation-queue as Invalidation-Wait-Descriptor as follows: +Status-Data=1 + // +Status-Address=address of variable tmp[unit +SW=1 +FN=1 +IF=0 + // + + Addr[2] = ((UINT64)1 << 32) + (06 << 04) + 05; // Invalidation Wait Descriptor + + TempQWord[RemapEng] = 00; + Addr[3] = (UINTN)&TempQWord[RemapEng]; // Status Address [63:2] bits[127:65] + + // + // 3. Program the IRTA register to point to the IRT table. + // For each VT-d unit in the platform, program interrupt-remap-table address and enable extended-interrupt-mode as follows + // + IRTA = (UINT64 *)((UINT64)VtdBarAddress + R_VTD_IRTA_REG); + Value = *(volatile UINT32 *)((UINT64)VtdBarAddress+ R_VTD_GSTS_REG); + // + // *(volatile UINT64*)IRTA = 04 + 0x800 + (UINT64)xApicAddr ; // [0:3] size = 2 Power (X+1). Bit11 =1 Xapic mode Bit[12:63] address + // + if (DmarPrivateData->Dmar->Flags && EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT) { + *(volatile UINT64*)IRTA = 07 + (UINT64)xApicAddr ; // [0:3] size = 2 Power (X+1). Bit11 =1 Xapic mode Bit[12:63] address + *(volatile UINT32 *)((UINT64)VtdBarAddress+ R_VTD_GCMD_REG) = (UINT32)(Value | BIT23); + } else { + *(volatile UINT64*)IRTA = 07 + 0x800 + (UINT64)xApicAddr ; // [0:3] size = 2 Power (X+1). Bit11 =1 Xapic mode Bit[12:63] addrerss + } + // + // b. Set SIRTP in the command register. + // + Count = 0x1000; + *(volatile UINT32 *)((UINT64)VtdBarAddress+ R_VTD_GCMD_REG) = (UINT32)(Value | BIT24); + + // + // Wait till the status bit is set indicating the completion of the SIRTP. + // + while (Count) { + Count--; + Value = *(volatile UINT32 *)((UINT64)VtdBarAddress + R_VTD_GSTS_REG); + if (Value & BIT24) { + break; + } + } + if (Count == 0) { + ASSERT(FALSE); + CpuDeadLoop (); + } + *(volatile UINT64 *)((UINT64)VtdBarAddress+ R_VTD_IQA_REG) = (UINT64)Addr; + } // End of if (VtdBarAddress) + } // End of for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) + } + + for (RemapEng = 0; RemapEng < RemapEngCount; RemapEng++) { + + for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) { + + // + // Check for valid stack + // + if (!(mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[RemapEng].stackPresentBitmap & (1 << Stack))) { + continue; + } + VtdBarAddress = DynamicSiLibraryProtocol2->GetVtdBar (RemapEng, Stack); + if (VtdBarAddress) { + + // + // 4. For each VT-d unit in the platform, setup invalidation-queue base registers and enable invalidation as follows + // Initialize a single descriptor which invalidates all the interrupt entries. + // IQA register write (zeros IQH and IQT) + // + + // + // Enable queued invalidation in the command register. + // + Count = 0x1000; + Value = *(volatile UINT32 *)((UINT64)VtdBarAddress+ R_VTD_GSTS_REG); + *(volatile UINT32 *)((UINT64)VtdBarAddress + R_VTD_GCMD_REG) = (UINT32)(Value | BIT26); + + while (Count) { + Count--; + Value = *(volatile UINT32 *)((UINT64)VtdBarAddress+ R_VTD_GSTS_REG); + if( Value & BIT26) { + break; + } + } + if (Count == 0) { + ASSERT(FALSE); + CpuDeadLoop (); + } + + // + // Start invalidations, program the IQT register + // Write the invalidation queue tail (IQT_REG) register as follows to indicate to hardware two descriptors are submitted: + // +Bits 63:19 are 0 +Bits 18:4 gets value of 2h +Bits 3:0 are 0 + // + + *(volatile UINT64 *)((UINT64)VtdBarAddress + R_VTD_IQT_REG) = (02 << 04); // Set tail to 02 + } // End of if (VtdAddress) + } //End of for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) + } + + for (RemapEng = 0; RemapEng < RemapEngCount; RemapEng++) { + + for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) { + + if (!(mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[RemapEng].stackPresentBitmap & (1 << Stack))) { + continue; // Skip invalid stacks + } + VtdBarAddress = DynamicSiLibraryProtocol2->GetVtdBar (RemapEng, Stack); + if (VtdBarAddress) { + // + // 5. For each VT-d unit in the platform, wait for invalidation completion, and enable interrupt remapping as follows + // Wait till the previously submitted invalidation commands are completed as follows + // Poll on the variable tmp[unit] in memory, until its value is 1h. + // + Count = 0x1000; + while (Count) { + Count--; + Value = TempQWord[RemapEng]; + if (Value & 01) { + break; + } + } + if (Count == 0) { + ASSERT(FALSE); + CpuDeadLoop (); + } + } // End of if VtdBarAddress + } //End of for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) + } + + // + // 5. Enable external interrupts in the IOAPIC RTE entry 0 + // + *(volatile UINT32 *)((UINT64)PCH_IOAPIC_ADDRESS) = 0x10; + *(volatile UINT32 *)((UINT64)PCH_IOAPIC_ADDRESS + 0x10) = 0x00; // Set index to the IRTE0 + + *(volatile UINT32 *)((UINT64)PCH_IOAPIC_ADDRESS) = 0x10+1; + *(volatile UINT32 *)((UINT64)PCH_IOAPIC_ADDRESS + 0x10) = 0x10000;// Set Remap enable bit +} + + +/** + Build DRHD entry into ACPI DMAR table for specific stack. + Include IOxAPIC, PCIExpress ports, and CBDMA if C-STACK. + + @param DmaRemap - pointer to DMA remapping protocol + @param IioIndex - IIO index to be processed + @param Stack - stack index to be processed + @param DevScope - buffer for device scope data structure + @param PciNode - buffer for PCI node data structure + @param PciRootBridgePtr- pointer to PciRootBridgeIo protocol for PCI access + + @retval EFI_SUCCESS - DRHD entry built successfully +**/ +EFI_STATUS +BuildDRHDForStack ( + DMA_REMAP_PROTOCOL *DmaRemap, + UINT8 IioIndex, + UINT8 Stack, + DEVICE_SCOPE *DevScope, + PCI_NODE *PciNode, + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgePtr, + UINT8 ApicIndex + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINT8 Bus; + UINT8 Dev; + UINT8 Func; + UINT8 DevIndex; + UINT8 PciNodeIndex; + UINT8 PortIndex; + UINT8 MaxPortNumberPerSocket; + UINT8 CBIndex; + UINT64 VtdMmioExtCap; + UINT32 VtdBase; + UINT32 VidDid; + DMAR_ATSR *pAtsr = NULL; + DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL; + + Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return EFI_NOT_FOUND; + } + + ASSERT (mIioUds2); + if (Stack > MAX_IIO_STACK){ + return EFI_UNSUPPORTED; + } + if (PciRootBridgePtr == NULL) { + ASSERT (!(PciRootBridgePtr == NULL)); + return EFI_INVALID_PARAMETER; + } + + mDrhd.Flags = 0; // all non-legacy stack has INCLUDE_ALL flag cleared + + VtdBase = DynamicSiLibraryProtocol2->GetVtdBar (IioIndex, Stack); + + if (VtdBase == 0) { + return EFI_UNSUPPORTED; + } + + VtdMmioExtCap = *(volatile UINT64*)((UINTN)VtdBase + R_VTD_EXT_CAP_LOW); + mDrhd.RegisterBase = VtdBase; + + DevIndex = 00; + PciNodeIndex = 00; + mDrhd.DeviceScopeNumber = 00; + ZeroMem (DevScope, MEMORY_SIZE * sizeof (DEVICE_SCOPE)); + ZeroMem (PciNode, MEMORY_SIZE * sizeof (PCI_NODE)); + + // + // DRHD - CBDMA entry + // + if (Stack == IIO_STACK0) { + + for (CBIndex = 0; CBIndex <= 7; CBIndex++) { + + DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT; + DevScope[DevIndex].EnumerationID = 00; + DevScope[DevIndex].StartBusNumber = mCpuCsrAccessVarPtr ->StackBus[IioIndex][IIO_STACK0]; + DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex]; + + PciNode[PciNodeIndex].Device = IOAT_DEVICE_NUM_10NM; + PciNode[PciNodeIndex].Function = CBIndex; + DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d] Build DRHD CBDMA: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n", + IioIndex, Stack, + DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber, + DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function)); + DevIndex++; + PciNodeIndex++; + PciNode[PciNodeIndex].Device = (UINT8) -1; + PciNode[PciNodeIndex].Function = (UINT8) -1; + PciNodeIndex++; + + mDrhd.DeviceScopeNumber++; + } // End of for for(CBIndex = 0; CBIndex <= 07; CBIndex++) + } + + // + // DRHD - PCI-Ex ports + // + pAtsr = GetDmarAtsrTablePointer (); + MaxPortNumberPerSocket = DynamicSiLibraryProtocol2->GetMaxPortPerSocket (IioIndex); + for (PortIndex = 1; PortIndex < MaxPortNumberPerSocket; PortIndex++) { + + if (DynamicSiLibraryProtocol2->GetStackPerPort (IioIndex, PortIndex) != Stack) { + continue; + } + Bus = DynamicSiLibraryProtocol2->GetSocketPortBusNum (IioIndex, PortIndex); + Dev = 0; + Func = 0; + if (pAtsr != NULL) { + Dev = pAtsr->DeviceScope[PortIndex].PciNode->Device; + Func = pAtsr->DeviceScope[PortIndex].PciNode->Function; + } + if (DynamicSiLibraryProtocol2->IioNtbIsEnabled (IioIndex, PortIndex, &Dev, &Func)) { + + DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT; + } else { + DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE; + } + // + // Skip root ports which do not respond to PCI configuration cycles. + // + VidDid = 0; + Status = PciRootBridgePtr->Pci.Read ( + PciRootBridgePtr, + EfiPciWidthUint32, + EFI_PCI_ADDRESS (Bus, Dev, Func, 0), + 1, + &VidDid); + if (EFI_ERROR (Status) || VidDid == 0xffffffff) { + + DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] %02X:%02X:%02X.%d Hidden (%X) - skip\n", + IioIndex, Stack, PortIndex, + mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[IioIndex].PcieSegment, + Bus, Dev, Func, VidDid)); + continue; + } + if (DynamicSiLibraryProtocol2->IioVmdPortIsEnabled (IioIndex, PortIndex) || DynamicSiLibraryProtocol2->GetCurrentPXPMap (IioIndex, PortIndex) == 0) { + + DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] %a - skip\n", IioIndex, Stack, PortIndex, + (DynamicSiLibraryProtocol2->GetCurrentPXPMap (IioIndex, PortIndex) == 0) ? "Link width not set" : "Dummy VMD function")); + continue; + } + DevScope[DevIndex].EnumerationID = 00; + DevScope[DevIndex].StartBusNumber = Bus; + DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex]; + PciNode[PciNodeIndex].Device = Dev; + PciNode[PciNodeIndex].Function = Func; + DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] Build DRHD PCI: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n", + IioIndex, Stack, PortIndex, + DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber, + DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function)); + DevIndex++; + PciNodeIndex++; + PciNode[PciNodeIndex].Device = (UINT8) -1; + PciNode[PciNodeIndex].Function = (UINT8) -1; + PciNodeIndex++; + + mDrhd.DeviceScopeNumber++; + } // for (PortIndex...) + + Status = DynamicSiLibraryProtocol2->IioVmdGetPciLocation (IioIndex, Stack, + &PciNode[PciNodeIndex].Device, &PciNode[PciNodeIndex].Function); + if (!EFI_ERROR (Status)) { + // + // VMD is enabled in this stack, expose VMD PCI device in DMAR for DMA remapping. + // + DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT; + DevScope[DevIndex].EnumerationID = 00; + DevScope[DevIndex].StartBusNumber = mCpuCsrAccessVarPtr->StackBus[IioIndex][Stack]; + DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex]; + DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d] Build DRHD VMD: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n", + IioIndex, Stack, + DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber, + DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function)); + DevIndex++; + PciNodeIndex++; + PciNode[PciNodeIndex].Device = (UINT8)-1; + PciNode[PciNodeIndex].Function = (UINT8)-1; + PciNodeIndex++; + + mDrhd.DeviceScopeNumber++; + } + + DmaRemap->InsertDmaRemap (DmaRemap, DrhdType, &mDrhd); + + return EFI_SUCCESS; +} + + +EFI_STATUS +ReportDmar ( + IN DMA_REMAP_PROTOCOL *DmaRemap + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINT8 SocketIndex, IioBusBase, Bus; + UINT8 Dev, Func; + UINT8 DevIndex; + UINT8 PciNodeIndex; + UINT8 PciPortIndex; + UINT8 MaxPortNumberPerSocket; + UINT64 VtdMmioExtCap; + UINT32 VtdBase; + VTD_SUPPORT_INSTANCE *DmarPrivateData; + UINT16 NumberOfHpets; + UINT16 HpetCapIdValue; + DEVICE_SCOPE *DevScope; + PCI_NODE *PciNode; + EFI_PHYSICAL_ADDRESS Pointer; + UINT32 AlignedSize; + UINT32 NumberofPages; + BOOLEAN IntrRemapSupport; + EFI_CPUID_REGISTER CpuidRegisters; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgePtr; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeTab[MAX_SOCKET]; + UINT32 VidDid; + UINT8 Index; + UINT8 Stack = 0; + UINT8 FirstRun = 0; + VOID *HobPtr; + PCH_INFO_HOB *PchInfoHob; + DMAR_ATSR *pAtsr = NULL; + UINT8 ApicIndex = 1; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL; + + Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return FALSE; + } + + HobPtr = GetFirstGuidHob (&gPchInfoHobGuid); + if (HobPtr == NULL) { + ASSERT (HobPtr != NULL); + return EFI_INVALID_PARAMETER; + } + + PchInfoHob = (PCH_INFO_HOB*) GET_GUID_HOB_DATA (HobPtr); + if (PchInfoHob == NULL) { + ASSERT (PchInfoHob != NULL); + return EFI_INVALID_PARAMETER; + } + + ASSERT (mIioUds2); + + DmarPrivateData = VTD_SUPPORT_INSTANCE_FROM_THIS (DmaRemap); + // + // Get DMAR_HOST_ADDRESS_WIDTH from CPUID.(EAX=80000008h) return the Phyical Address + // Size in the EAX register. EAX[7:0] + // Sync with Brickland code DMAR_HOST_ADDRESS_WIDTH 45 = 46 - 1 + // + AsmCpuid ( + CPUID_VIR_PHY_ADDRESS_SIZE, + &CpuidRegisters.RegEax, + &CpuidRegisters.RegEbx, + &CpuidRegisters.RegEcx, + &CpuidRegisters.RegEdx + ); + + DmarPrivateData->Dmar->HostAddressWidth = (UINT8)((CpuidRegisters.RegEax & 0xFF)-1); + DmarPrivateData->Dmar->Flags = 0; // INTR_REMAP + + // + // Locate PCI root bridge I/O protocol, for confirming PCI functions respond + // to PCI configuration cycles. + // + ZeroMem (&PciRootBridgeTab[0], sizeof(PciRootBridgeTab)); + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + + ASSERT_EFI_ERROR (Status); + + for (Index = 0; Index < HandleCount; Index ++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciRootBridgeIoProtocolGuid, + &PciRootBridgePtr + ); + + ASSERT_EFI_ERROR (Status); + + PciRootBridgeTab[PciRootBridgePtr->SegmentNumber] = PciRootBridgePtr; + } + FreePool (HandleBuffer); + + // + // Allocate memory to DevScope structures + // + Status = gBS->AllocatePool (EfiACPIMemoryNVS, MEMORY_SIZE * sizeof (DEVICE_SCOPE), &DevScope); + ASSERT_EFI_ERROR (Status); + + Status = gBS->AllocatePool (EfiACPIMemoryNVS, MEMORY_SIZE * sizeof (PCI_NODE), &PciNode); + ASSERT_EFI_ERROR (Status); + + for (Index = 1; Index <= MAX_SOCKET; Index++) { + // + // VT-d specification request that DHRD entry 0 should be the latest entry of the DMAR table. + // To accomplish this, the following check will ensure that latest entry will be the one related to Socket 0. + // + if (Index == MAX_SOCKET) { + SocketIndex = 0; + } else { + SocketIndex = Index; + } + + if (SocketIndex >= MAX_SOCKET) { + return EFI_INVALID_PARAMETER; + } + + if (!DynamicSiLibraryProtocol2->SocketPresent (SocketIndex)) { + continue; + } + + if (mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment >= MAX_SOCKET) { + return EFI_INVALID_PARAMETER; + } + PciRootBridgePtr = PciRootBridgeTab[mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment]; + + Stack = IIO_STACK0; + VtdBase = DynamicSiLibraryProtocol2->GetVtdBar (SocketIndex, Stack); + + DevIndex = 00; + PciNodeIndex = 00; + + mDrhd.Signature = DRHD_SIGNATURE; + mDrhd.SegmentNumber = mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment; + mDrhd.DeviceScopeNumber = 00; + mDrhd.DeviceScope = DevScope; + mDrhd.RegisterBase = VtdBase; + ZeroMem (DevScope, MEMORY_SIZE * sizeof (DEVICE_SCOPE)); + ZeroMem (PciNode, MEMORY_SIZE * sizeof (PCI_NODE)); + + VtdMmioExtCap = *(volatile UINT64*)((UINTN)VtdBase + R_VTD_EXT_CAP_LOW); + + // + // Check Interrupt Remap support. + // + IntrRemapSupport = FALSE; + if (VtdMmioExtCap & INTRREMAP) { + IntrRemapSupport = TRUE; + } + DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d] VT-d base 0x%X, ExtCap=0x%X\n", + SocketIndex, Stack, VtdBase, VtdMmioExtCap)); + + if (SocketIndex == 0) { + ApicIndex = 1; + // + // DRHD - Legacy IOH + // + // Build DRHD on IIO0 - Stack1 to Stack5, not include C-STACK + // + for (Stack = 1; Stack < MAX_IIO_STACK; Stack++) { + + if (!DynamicSiLibraryProtocol2->IfStackPresent (SocketIndex, Stack)) { // Skip invalid stack + continue; + } + BuildDRHDForStack (DmaRemap, SocketIndex, Stack, DevScope, PciNode, PciRootBridgePtr, ApicIndex); + ApicIndex++; + } + + Stack = IIO_STACK0; + + // + // Re-initialize DRHD template for DRHD entry in legacy socket C-STACK + // + DevIndex = 00; + PciNodeIndex = 00; + mDrhd.DeviceScopeNumber = 00; + mDrhd.RegisterBase = DynamicSiLibraryProtocol2->GetVtdBar (SocketIndex, Stack); + ZeroMem (DevScope, MEMORY_SIZE * sizeof (DEVICE_SCOPE)); + ZeroMem (PciNode, MEMORY_SIZE * sizeof (PCI_NODE)); + + IioBusBase = mCpuCsrAccessVarPtr ->StackBus[SocketIndex][Stack]; // Stack 0 + mDrhd.Flags = 1; + + DEBUG ((DEBUG_INFO, "[ACPI](DMAR) InterruptRemap is %aabled (%d & %d)\n", + (DmaRemap->InterruptRemap && IntrRemapSupport) ? "en" : "dis", DmaRemap->InterruptRemap, IntrRemapSupport)); + if (DmaRemap->InterruptRemap && IntrRemapSupport) { + + DmarPrivateData->Dmar->Flags = 0x01; // INTR_REMAP + + if (DmaRemap->X2ApicOptOut) { + DmarPrivateData->Dmar->Flags |= 0x02; // X2APIC_OPT_OUT + } + // + // PCH - IOAPIC + // This information will be provided by PCH side + // Currently is a hard-coded temporal solution to set: + // Bus = 0; Device and Function (together) = 0xF7; + // This is the value that is stored in IBDF register: + //#define V_P2SB_CFG_IBDF_BUS 0 + //#define V_P2SB_CFG_IBDF_DEV 30 + //#define V_P2SB_CFG_IBDF_FUNC 7 + // + DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC; + DevScope[DevIndex].EnumerationID = PCH_IOAPIC_ID; // PCH team needs confirm this value. (This value affects VTd functionality?) + DevScope[DevIndex].StartBusNumber = (UINT8)PchInfoHob->IoApicBusNum; + DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex]; + + PciNode[PciNodeIndex].Device = (UINT8)PchInfoHob->IoApicDevNum; + PciNode[PciNodeIndex].Function = (UINT8)PchInfoHob->IoApicFuncNum; + DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d] Build DRHD PCH IOAPIC: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n", + SocketIndex, Stack, + DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber, + DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function)); + DevIndex++; + PciNodeIndex++; + PciNode[PciNodeIndex].Device = (UINT8)-1; + PciNode[PciNodeIndex].Function = (UINT8)-1; + PciNodeIndex++; + + mDrhd.DeviceScopeNumber++; + + HpetCapIdValue = *(UINT16 *)(UINTN)(HPET_BLOCK_ADDRESS); + NumberOfHpets = (HpetCapIdValue >> 0x08) & 0x1F; // Bits [8:12] contains the number of Hpets + + if (NumberOfHpets && (NumberOfHpets != 0x1f) && + (*((volatile UINT32 *)(UINTN)(HPET_BLOCK_ADDRESS + 0x100)) & BIT15)) { + + DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET; + DevScope[DevIndex].EnumerationID = 00; //Hard-coded + DevScope[DevIndex].StartBusNumber = (UINT8)PchInfoHob->HpetBusNum; + DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex]; + PciNode[PciNodeIndex].Device = (UINT8)PchInfoHob->HpetDevNum; + PciNode[PciNodeIndex].Function = (UINT8)PchInfoHob->HpetFuncNum; + DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d] Build DRHD HPET: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n", + SocketIndex, Stack, + DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber, + DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function)); + DevIndex++; + PciNodeIndex++; + PciNode[PciNodeIndex].Device = (UINT8)-1; + PciNode[PciNodeIndex].Function = (UINT8)-1; + PciNodeIndex++; + + mDrhd.DeviceScopeNumber++; + } + } // DmaRemap->InterruptRemap + + DEBUG ((DEBUG_INFO, "[ACPI](DMAR) DMA_CTRL_PLATFORM_OPT_IN_FLAG is %aabled\n", (DmaRemap->DmaCtrlOptIn) ? "En" : "Dis")); + if (DmaRemap->DmaCtrlOptIn) { + + DmarPrivateData->Dmar->Flags |= 0x04; // DMA_CTRL_PLATFORM_OPT_IN_FLAG + } + DmaRemap->InsertDmaRemap (DmaRemap, DrhdType, &mDrhd); + + } else { // End of if (IioSocketId == 0) + + if (FirstRun == 0) { + ApicIndex = 0; + for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) { + // + // Skip not valid stack + // + if (!DynamicSiLibraryProtocol2->IfStackPresent (0 ,Stack)) { + continue; + } + ApicIndex++; + } + FirstRun = 1; + } + // + // Build DRHD on IIO1 - Stack0 to Stack5 + // + for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) { + // + // Skip not valid stack + // + if (!DynamicSiLibraryProtocol2->IfStackPresent (SocketIndex,Stack)) { + continue; + } + BuildDRHDForStack (DmaRemap, SocketIndex, Stack, DevScope, PciNode, PciRootBridgePtr, ApicIndex); + ApicIndex++; + } //for( StackIndex=0; StackIndexATS) { + for (SocketIndex = 0; SocketIndex < MAX_SOCKET; SocketIndex++) { + + DEBUG((DEBUG_ERROR, "T_TEST: Build ATSR SocketIndex=%d.\n", SocketIndex)); + DEBUG((DEBUG_ERROR, " IIO_resource.valid=%d.\n", mIioUds2->IioUdsPtr->PlatformData.IIO_resource[SocketIndex].Valid)); + + if (SocketIndex >= MAX_SOCKET) { + return EFI_INVALID_PARAMETER; + } + + if (!DynamicSiLibraryProtocol2->SocketPresent (SocketIndex)) { + continue; + } + + IioBusBase = mIioUds2->IioUdsPtr->PlatformData.IIO_resource[SocketIndex].BusBase; + + if (mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment >= MAX_SOCKET) { + return EFI_INVALID_PARAMETER; + } + PciRootBridgePtr = PciRootBridgeTab[mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment]; + + PciNodeIndex = 00; + DevIndex = 00; + + ZeroMem (DevScope, MEMORY_SIZE * sizeof (DEVICE_SCOPE)); + ZeroMem (PciNode, MEMORY_SIZE * sizeof (PCI_NODE)); + + if (pAtsr != NULL) { + pAtsr->Signature = ATSR_SIGNATURE; + pAtsr->Flags = 00; + pAtsr->SegmentNumber = mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment; + pAtsr->DeviceScopeNumber = 00; + pAtsr->DeviceScope = DevScope; + pAtsr->ATSRPresentBit = (UINT32)-1; // Not useful really Backwards project compatability (remove it later) + } + + // + // Loop From Port 1 to 15 for Legacy IOH and 0 to 15 for Non-Legacy IOH + // + MaxPortNumberPerSocket = DynamicSiLibraryProtocol2->GetMaxPortPerSocket (SocketIndex); + for (PciPortIndex = 1; PciPortIndex < MaxPortNumberPerSocket; PciPortIndex++) { + // + // Check device IOTLBs supported or not in VT-d Extended capability register + // + Stack = DynamicSiLibraryProtocol2->GetStackPerPort (SocketIndex, PciPortIndex); + // + // Check for a valid stack + // + if (!(DynamicSiLibraryProtocol2->IfStackPresent (SocketIndex, Stack))) { + DEBUG ((DEBUG_WARN, "[ACPI](DMAR) [%d.%d p%d] Stack not present\n", SocketIndex, Stack, PciPortIndex)); + continue; + } + + VtdBase = DynamicSiLibraryProtocol2->GetVtdBar (SocketIndex, Stack); + if (VtdBase != 0) { + + VtdMmioExtCap = *(volatile UINT64*)((UINTN)VtdBase + R_VTD_EXT_CAP_LOW); + // + // ATSR is applicable only for platform supporting device IOTLBs through the VT-d extended capability register + // + if ((VtdMmioExtCap & BIT2) != 0) { + + Bus = DynamicSiLibraryProtocol2->GetSocketPortBusNum (SocketIndex,PciPortIndex); + Dev = 0; + Func = 0; + Dev = mDevScopeATSR10nm[PciPortIndex].PciNode->Device; + Func = mDevScopeATSR10nm[PciPortIndex].PciNode->Function; + if (DynamicSiLibraryProtocol2->IioNtbIsEnabled (SocketIndex, PciPortIndex, &Dev, &Func)) { + DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT; + } else { + DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE; + } + // + // Skip root ports which do not respond to PCI configuration cycles. + // + VidDid = 0; + Status = PciRootBridgePtr->Pci.Read ( + PciRootBridgePtr, + EfiPciWidthUint32, + EFI_PCI_ADDRESS (Bus, Dev, Func, 0), + 1, + &VidDid); + if (EFI_ERROR (Status) || VidDid == 0xffffffff) { + + DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] %02X:%02X:%02X.%d Hidden (%X) - skip\n", + SocketIndex, Stack, PciPortIndex, + mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment, + Bus, Dev, Func, VidDid)); + continue; + } + if (DynamicSiLibraryProtocol2->IioVmdPortIsEnabled (SocketIndex, PciPortIndex) || DynamicSiLibraryProtocol2->GetCurrentPXPMap (SocketIndex, PciPortIndex) == 0) { + + DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] %a - skip\n", SocketIndex, Stack, PciPortIndex, + (DynamicSiLibraryProtocol2->GetCurrentPXPMap (SocketIndex, PciPortIndex) == 0) ? "Link width not set" : "Dummy VMD function")); + continue; + } + DevScope[DevIndex].EnumerationID = 00; + DevScope[DevIndex].StartBusNumber = Bus; + DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex]; + PciNode[PciNodeIndex].Device = Dev; + PciNode[PciNodeIndex].Function = Func; + DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] Build DRHD PCI: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n", + SocketIndex, Stack, PciPortIndex, + DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber, + DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function)); + DevIndex++; + PciNodeIndex++; + PciNode[PciNodeIndex].Device = (UINT8) -1; + PciNode[PciNodeIndex].Function = (UINT8) -1; + PciNodeIndex++; + if(pAtsr != NULL){ + pAtsr->DeviceScopeNumber++; + } + } // End of if ((VtdMmioExtCap & BIT2) != 0) + } // End of if VtdBase + } // for (PciPortIndex...) + + if (pAtsr != NULL){ + if (pAtsr->DeviceScopeNumber) { + DmaRemap->InsertDmaRemap(DmaRemap, AtsrType, pAtsr); + } + } + } // End of for (RootBridgeLoop = 0; RootBridgeLoop < mIioUds2->IioUdsPtr->PlatformData.numofIIO; RootBridgeLoop++) + } // End of if (ATS) { + + // + // RMRR + // + AlignedSize = (MEM_BLK_COUNT * sizeof(MEM_BLK)); + if (AlignedSize % 0x1000) { + AlignedSize = ( (MEM_BLK_COUNT * sizeof(MEM_BLK)) & (~0xfff) ) + 0x1000; + } // aligend to 4k Boundary + NumberofPages = AlignedSize/0x1000; + // + // Allocate memory (below 4GB) + // + Pointer = 0xffffffff; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiReservedMemoryType, + NumberofPages, + &Pointer // Base address need to be 4K aligned for VT-d RMRR + ); + ASSERT_EFI_ERROR (Status); + + if (DmaRemap->VTdSupport) { + // + // RMRR + // + mRmrr.DeviceScope = &DevScopeRmrr[0]; + // + // Calculate the right size of DevScope for mRmrr entry + // + mRmrr.DeviceScopeNumber = sizeof(DevScopeRmrr) / sizeof(DEVICE_SCOPE); + mRmrr.RsvdMemBase = (UINT64)Pointer; + mRmrr.RsvdMemLimit = mRmrr.RsvdMemBase + AlignedSize - 1; + DEBUG ((DEBUG_INFO, "[ACPI](DMAR) RMRR Base 0x%llX, Limit 0x%llX\n", mRmrr.RsvdMemBase, mRmrr.RsvdMemLimit)); + DmaRemap->InsertDmaRemap (DmaRemap, RmrrType, &mRmrr); + } + gBS->FreePool (PciNode); + gBS->FreePool (DevScope); + + return EFI_SUCCESS; +} + + +/** + Install ACPI DMAR table for VT-d. + + This function needs gEfiPciIoProtocolGuid so it can run only after PCI Enumeraion is complete. + + @retval EFI_SUCCESS DMAR installed successfuly. + @retval EFI_NOT_FOUND gEfiPciIoProtocolGuid or gDmaRemapProtocolGuid not found. + @retval EFI_OUT_OF_RESOURCES Could not allocate resources. +**/ +EFI_STATUS +AcpiVtdTablesInstall ( + VOID + ) +{ + EFI_STATUS Status; + EFI_ACPI_TABLE_VERSION TableVersion; + DMA_REMAP_PROTOCOL *DmaRemap; + UINTN TableHandle; + EFI_ACPI_COMMON_HEADER *CurrentTable; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE01 PciConfigHeader; + UINTN Segment; + UINTN Bus; + UINTN Device; + UINTN Function; + UINT8 PciExpressOffset; + UINT32 AcsOffset; + UINT16 PciExpressCapabilityReg; + UINT8 AcsCapCount; + UINT16 RequiredAcsCap; + UINT32 AcsCapRegValue; + UINT16 AcsConRegValue; + USRA_PCIE_ADDR_TYPE *AcsDevArray; + USRA_ADDRESS Address; + + DYNAMIC_SI_LIBARY_PROTOCOL *DynamicSiLibraryProtocol = NULL; + + Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &DynamicSiLibraryProtocol); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return EFI_NOT_FOUND; + } + + PciExpressOffset = 0; + AcsOffset = 0; + AcsCapCount = 0; + AcsCapRegValue = 0; + AcsConRegValue = 0; + RequiredAcsCap = ACS_SOURCE_VALIDATION | ACS_P2P_REQUEST_REDIRECT | ACS_P2P_COMPLETION_REDIRECT | ACS_UPSTREAM_FORWARDING; + + // + // Locate all PciIo protocols + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + + DEBUG((DEBUG_ERROR, "[ACPI](DMAR) ERROR: Cannot locate gEfiPciIoProtocolGuid (%r)\n", Status)); + ASSERT (FALSE); + return Status; + } + AcsDevArray = AllocateZeroPool (sizeof (USRA_PCIE_ADDR_TYPE) * HandleCount); + if (AcsDevArray == NULL) { + ASSERT (AcsDevArray != NULL); + return EFI_OUT_OF_RESOURCES; + } + + for (Index = 0; Index < HandleCount; Index ++) { + + gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, &PciIo); + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof(PciConfigHeader) / sizeof(UINT32), &PciConfigHeader); + if ((PciConfigHeader.Hdr.ClassCode[0] == 0x00 || PciConfigHeader.Hdr.ClassCode[0] == 0x01) && PciConfigHeader.Hdr.ClassCode[1] == 0x04 && PciConfigHeader.Hdr.ClassCode[2] == 0x06) { + // + // 060400h or 060401h indicates it's PCI-PCI bridge, get its bus number, device number and function number + // + + PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function); + + USRA_PCIE_SEG_ADDRESS(Address, UsraWidth16, Segment, Bus, Device, Function, 0); + + if (PciConfigHeader.Hdr.Status == EFI_PCI_STATUS_CAPABILITY) { + // + // the bridge support Capability list and offset 0x34 is the pointer to the data structure + // + // Detect if PCI Express Device + // + Status = LocateCapRegBlock (PciIo, EFI_PCI_CAPABILITY_ID_PCIEXP, &PciExpressOffset, NULL); + + if (Status == EFI_SUCCESS) { + // + // this bridge device is a PCI Express bridge + // Check if it is downstream port of PCIE switch + // + Address.Pcie.Offset = PciExpressOffset + EFI_PCI_EXPRESS_CAPABILITY_REGISTER; + DynamicSiLibraryProtocol->RegisterRead(&Address, &PciExpressCapabilityReg); + + // + // BIT 7:4 indicate Device/port type, 0110b indicates downstream port of PCI express switch + // + if ((PciExpressCapabilityReg & 0x00F0) == 0x60) { + // + // it is downstream port of PCI Express switch + // Look for ACS capability register in PCI express configuration space + // + Status = LocatePciExpressCapRegBlock (PciIo, EFI_PCIE_CAPABILITY_ID_ACS, &AcsOffset, NULL); + DEBUG((DEBUG_ERROR, "ACS capable port is B%x.D%x.F%x - ACS Cap offset - 0x%x\n", Bus, Device, Function, AcsOffset)); + + if (Status == EFI_SUCCESS) { + // + // Read ACS capability register + // + Address.Pcie.Offset = AcsOffset + ACS_CAPABILITY_REGISTER; + Address.Attribute.AccessWidth = UsraWidth32; + DynamicSiLibraryProtocol->RegisterRead(&Address, &AcsCapRegValue); + DEBUG((DEBUG_INFO, "Bus =%x, Device=%x, Function=%x, AcsCapRegValue = %x \n", Bus, Device, Function, AcsCapRegValue)); + + if ((AcsCapRegValue & RequiredAcsCap) == RequiredAcsCap) { + // + // The PCI express downstream port support ACS, record this port + // + AcsDevArray[AcsCapCount].Bus = (UINT32)Bus; + AcsDevArray[AcsCapCount].Dev = (UINT32)Device; + AcsDevArray[AcsCapCount].Func = (UINT32)Function; + AcsDevArray[AcsCapCount].Offset = AcsOffset; + AcsDevArray[AcsCapCount].Seg = (UINT32)Segment; + AcsCapCount++; + } + } + } + } + } + } + } /// End for + + // + // Free the Handle buffer + // + if (HandleBuffer != NULL) { + gBS->FreePool (HandleBuffer); + } + + ASSERT (AcsCapCount <= HandleCount); + + // + // all PCI express switch downstream ports support ACS and meet the required ACS capabilities + // for each downstream ports, enable the required Capabilities in ACS control register + // + Address.Attribute.AccessWidth = UsraWidth16; + for (Index = 0; Index < AcsCapCount; Index ++) { + // + // Program the corresponding bits in ACS control register + // + Address.Pcie = AcsDevArray[Index]; + Address.Pcie.Offset += ACS_CONTROL_REGISTER; + DynamicSiLibraryProtocol->RegisterRead (&Address, &AcsConRegValue); + DEBUG ((DEBUG_ERROR, "AcsConRegValue is 0x%x\n", AcsConRegValue)); + AcsConRegValue |= (ACS_SOURCE_VALIDATION_ENABLE | ACS_P2P_REQUEST_REDIRECT_ENABLE | ACS_P2P_COMPLETION_REDIRECT_ENABLE | ACS_UPSTREAM_FORWARDING_ENABLE); + DEBUG ((DEBUG_ERROR, "After Enable BITs AcsConRegValue is 0x%x\n", AcsConRegValue)); + DynamicSiLibraryProtocol->RegisterWrite (&Address, &AcsConRegValue); + // + // report VT-d and other features to OS/VMM, report DMAR and remapping engine to OS/VMM + // + } + + // + // Find the AcpiSupport protocol + // + Status = LocateSupportProtocol (&gEfiAcpiTableProtocolGuid, gEfiAcpiTableStorageGuid, &AcpiTable, FALSE); + ASSERT_EFI_ERROR (Status); + + TableVersion = EFI_ACPI_TABLE_VERSION_2_0; + + Status = gBS->LocateProtocol (&gDmaRemapProtocolGuid, NULL, &DmaRemap); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "[ACPI](DMAR) ERROR: Cannot locate gDmaRemapProtocolGuid (%r)\n", Status)); + } else { + if (DmaRemap->VTdSupport) { + ReportDmar (DmaRemap); + Status = DmaRemap->GetDmarTable (DmaRemap, &CurrentTable); + + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + } else { + // + // Perform any table specific updates. + // + Status = PlatformUpdateTables (CurrentTable, &TableVersion); + ASSERT_EFI_ERROR (Status); + + TableHandle = 0; + Status = AcpiTable->InstallAcpiTable ( + AcpiTable, + CurrentTable, + CurrentTable->Length, + &TableHandle + ); + ASSERT_EFI_ERROR (Status); + } + } + } + FreePool (AcsDevArray); + + return EFI_SUCCESS; +} + + +EFI_STATUS +LocateCapRegBlock ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT8 CapID, + OUT UINT8 *PciExpressOffset, + OUT UINT8 *NextRegBlock + ) +{ + UINT16 CapabilityID; + UINT32 Temp; + UINT8 CapabilityPtr; + UINT16 CapabilityEntry; + + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + PCI_CAPBILITY_POINTER_OFFSET, + 1, + &Temp + ); + + CapabilityPtr = (UINT8)Temp; + // + // According to the PCI spec a value of 0x00 + // is the end of the list + // + while (CapabilityPtr >= 0x40) { + // + // Mask it to DWORD alignment per PCI spec + // + CapabilityPtr &= 0xFC; + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint16, + CapabilityPtr, + 1, + &CapabilityEntry + ); + + CapabilityID = (UINT8) CapabilityEntry; + + if (CapabilityID == CapID) { + *PciExpressOffset = CapabilityPtr; + if (NextRegBlock != NULL) { + *NextRegBlock = (UINT8) ((CapabilityEntry >> 8) & 0xFC); + } + + return EFI_SUCCESS; + } + + CapabilityPtr = (UINT8) ((CapabilityEntry >> 8) & 0xFC); + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +LocatePciExpressCapRegBlock ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 CapID, + OUT UINT32 *Offset, + OUT UINT32 *NextRegBlock +) +{ + UINT32 CapabilityPtr; + UINT32 CapabilityEntry; + UINT16 CapabilityID; + + CapabilityPtr = EFI_PCIE_CAPABILITY_BASE_OFFSET; + + while ((CapabilityPtr != 0) && (CapabilityPtr < 0x1000)) { + // + // Mask it to DWORD alignment per PCI spec + // + CapabilityPtr &= 0xFFC; + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + CapabilityPtr, + 1, + &CapabilityEntry + ); + + CapabilityID = (UINT16) CapabilityEntry; + + if (CapabilityID == CapID) { + *Offset = CapabilityPtr; + if (NextRegBlock != NULL) { + *NextRegBlock = (CapabilityEntry >> 20) & 0xFFF; + } + + return EFI_SUCCESS; + } + + CapabilityPtr = (CapabilityEntry >> 20) & 0xFFF; + } + + return EFI_NOT_FOUND; +} + + +VOID +DisableAriForwarding ( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE01 PciConfigHeader; + UINTN Segment; + UINTN Bus; + UINTN Device; + UINTN Function; + UINT8 PciExpressOffset; + PCI_REG_PCIE_DEVICE_CONTROL2 DevCtl2; + + // + // Disable ARI forwarding before handoff to OS, as it may not be ARI-aware + // + // + // ARI forwarding exist in bridge + // + + // + // Locate all PciIo protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + for (Index = 0; Index < HandleCount; Index ++) { + gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + &PciIo + ); + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfigHeader) / sizeof (UINT32), + &PciConfigHeader + ); + if ((PciConfigHeader.Hdr.ClassCode[0] == 0x00 || PciConfigHeader.Hdr.ClassCode[0] == 0x01) && PciConfigHeader.Hdr.ClassCode[1] == 0x04 && PciConfigHeader.Hdr.ClassCode[2] == 0x06) { + // + // 060400h or 060401h indicates it's PCI-PCI bridge, get its bus number, device number and function number + // + PciIo->GetLocation ( + PciIo, + &Segment, + &Bus, + &Device, + &Function + ); + if (PciConfigHeader.Hdr.Status == EFI_PCI_STATUS_CAPABILITY) { + // + // the bridge support Capability list and offset 0x34 is the pointer to the data structure + // + // + // Detect if PCI Express Device + // + Status = LocateCapRegBlock (PciIo, EFI_PCI_CAPABILITY_ID_PCIEXP, &PciExpressOffset, NULL); + if (Status == EFI_SUCCESS) { + // + // this bridge device is a PCI Express bridge, Check ARI forwarding bit in Device Control 2 register + // + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint16, + PciExpressOffset + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2), + 1, + &DevCtl2 + ); + if (DevCtl2.Bits.AriForwarding) { + // + // ARI forwarding enable bit is set, we need to clear this bit before handing off control to OS + // because OS may not ARI aware + // + DEBUG((DEBUG_INFO, "[VTD] %02X:%02X:%02X.%X: ARI forwarding disable before booting OS, DevCtl2 0x%02X -> 0x%02X\n", + Segment, Bus, Device, Function, DevCtl2.Uint16, DevCtl2.Uint16 & ~BIT5)); + DevCtl2.Bits.AriForwarding = 0; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + PciExpressOffset + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2), + 1, + &DevCtl2 + ); + } + } + } + } + } +} // DisableAriForwarding() diff --git a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec index a80472e73c..27253b1a58 100644 --- a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec +++ b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec @@ -24,6 +24,7 @@ [Guids] gBiosInfoGuid = { 0x1b453c67, 0xcb1a, 0x46ec, { 0x86, 0x4b, 0xe2, 0x24, 0xa6, 0xb7, 0xfe, 0xe8 } } + gEfiAcpiTableStorageGuid = { 0x7e374e25, 0x8e01, 0x4fee, { 0x87, 0xf2, 0x39, 0x0c, 0x23, 0xc6, 0x06, 0xcd } } gClvBootTimeTestExecution = { 0x3ff7d152, 0xef86, 0x47c3, { 0x97, 0xb0, 0xce, 0xd9, 0xbb, 0x80, 0x9a, 0x67 } } gUbaCurrentConfigHobGuid = { 0xe4b2025b, 0xc7db, 0x4e5d, { 0xa6, 0x5e, 0x2b, 0x25, 0x7e, 0xb1, 0x5, 0x8e } } @@ -181,6 +182,11 @@ gPlatformTokenSpaceGuid.PcdSupportLegacyStack|TRUE|BOOLEAN|0x30000030 gPlatformTokenSpaceGuid.PcdMaxOptionRomNumber|0x4|UINT8|0x30000031 + # + # Debug Mode indicator + # + gPlatformTokenSpaceGuid.PcdDebugModeEnable|0x01|UINT8|0xE0000040 + gPlatformTokenSpaceGuid.PcdCmosDebugPrintLevelReg|0x4C|UINT8|0x30000032 # Choose the default serial debug message level when CMOS is bad; in the later BIOS phase, the setup default is applied @@ -238,11 +244,6 @@ gPlatformModuleTokenSpaceGuid.PcdPcIoApicInterruptBase|24|UINT32|0x90000018 - gPlatformModuleTokenSpaceGuid.PcdMaxCpuThreadCount|2|UINT32|0x90000021 - gPlatformModuleTokenSpaceGuid.PcdMaxCpuCoreCount|8|UINT32|0x90000022 - gPlatformModuleTokenSpaceGuid.PcdMaxCpuSocketCount|4|UINT32|0x90000023 - gPlatformModuleTokenSpaceGuid.PcdHpetTimerBlockId|0x8086A201|UINT32|0x90000024 - gPlatformModuleTokenSpaceGuid.PcdFadtPreferredPmProfile|0x02|UINT8|0x90000025 gPlatformModuleTokenSpaceGuid.PcdFadtIaPcBootArch|0x0001|UINT16|0x90000026 gPlatformModuleTokenSpaceGuid.PcdFadtFlags|0x000086A5|UINT32|0x90000027 diff --git a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc index 5dfee0eeb5..042c27c709 100644 --- a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc +++ b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc @@ -809,7 +809,10 @@ $(RP_PKG)/Features/Pci/Dxe/PciPlatform/PciPlatform.inf +!if $(CPUTARGET) == "ICX" + $(RP_PKG)/Features/Acpi/AcpiPlatform/AcpiPlatform.inf $(RP_PKG)/Features/Acpi/AcpiTables/AcpiTables10nm.inf +!endif $(RP_PKG)/Features/AcpiVtd/AcpiVtd.inf $(PLATFORM_PKG)/Acpi/AcpiSmm/AcpiSmm.inf diff --git a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf index ca3514b8ba..ab594ff409 100644 --- a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf +++ b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf @@ -671,7 +671,10 @@ SET gMinPlatformPkgTokenSpaceGuid.PcdFlashAreaSize = 0x01000000 INF BoardModulePkg/LegacySioDxe/LegacySioDxe.inf INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf +!if $(CPUTARGET) == "ICX" INF RuleOverride = ACPITABLE WhitleyOpenBoardPkg/Features/Acpi/AcpiTables/AcpiTables10nm.inf + INF WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.inf +!endif INF WhitleyOpenBoardPkg/Features/AcpiVtd/AcpiVtd.inf INF MinPlatformPkg/Acpi/AcpiSmm/AcpiSmm.inf diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Uba/UbaMain/StaticSkuDataDxe/Readme.md b/Platform/Intel/WhitleyOpenBoardPkg/Uba/UbaMain/StaticSkuDataDxe/Readme.md index 08fd02f922..58f9b88dae 100644 --- a/Platform/Intel/WhitleyOpenBoardPkg/Uba/UbaMain/StaticSkuDataDxe/Readme.md +++ b/Platform/Intel/WhitleyOpenBoardPkg/Uba/UbaMain/StaticSkuDataDxe/Readme.md @@ -16,4 +16,5 @@ The AmlOffsetTable.c file is generated in two key steps: Common Issues: * The same iasl compiler version must be used to build the AML offset table and to build the DSDT. +* The same iasl compiler version must be used to build the AML offset table and to build the DSDT. With the addition of -so for building the AML offset table. * The Board/*AmlOffsets*.dsc file name, Board/*AmlOffsets* directory name, Board/AmlOffsets/*AmlOffsets*.inf file name, and the BASE_NAME in *AmlOffsets*.inf must all match exactly. diff --git a/Platform/Intel/WhitleyOpenBoardPkg/WilsonCityRvp/AmlOffsets/AmlOffsets.inf b/Platform/Intel/WhitleyOpenBoardPkg/WilsonCityRvp/AmlOffsets/AmlOffsets.inf index 8945f372e3..859875ab5b 100644 --- a/Platform/Intel/WhitleyOpenBoardPkg/WilsonCityRvp/AmlOffsets/AmlOffsets.inf +++ b/Platform/Intel/WhitleyOpenBoardPkg/WilsonCityRvp/AmlOffsets/AmlOffsets.inf @@ -23,4 +23,4 @@ [BuildOptions] # add -vr and -so to generate offset.h - *_*_*_ASL_FLAGS = -oi -vr -so + *_*_*_ASL_FLAGS = -so -- 2.27.0.windows.1