alder_lake_bios/Intel/AlderLake/AlderLakeChipsetPkg/UnLockedBarHandleSmm/UnLockedBarHandleSmm.c

229 lines
7.0 KiB
C

/** @file
;******************************************************************************
;* Copyright (c) 2018, Insyde Software Corporation. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "UnLockedBarHandleSmm.h"
EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable;
EFI_STATUS
UnLockedBarHandleEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
VOID *PciEnumerationCompleteProtocol;
EFI_SMM_BASE2_PROTOCOL *SmmBase;
BOOLEAN InSmm;
SmmBase = NULL;
Status = gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, (VOID **)&SmmBase);
ASSERT_EFI_ERROR (Status);
Status = SmmBase->InSmm (SmmBase, &InSmm);
ASSERT_EFI_ERROR (Status);
if (!InSmm) {
return EFI_SUCCESS;
} else {
//
// In SMM
//
Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mSmmVariable);
ASSERT_EFI_ERROR (Status);
Status = gBS->LocateProtocol(&gEfiPciEnumerationCompleteProtocolGuid, NULL, &PciEnumerationCompleteProtocol);
ASSERT_EFI_ERROR (Status);
if (!EFI_ERROR(Status)) {
SaveUnLockedBar();
}
}
return EFI_SUCCESS;
}
BOOLEAN
IsSaveDynamicBar (
EFI_PCI_IO_PROTOCOL *PciIo,
UINTN BarIndex
)
{
BOOLEAN Save;
PCI_TYPE00 Pci;
UINTN Segment;
UINTN Bus;
UINTN Device;
UINTN Function;
Save = TRUE;
PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (PCI_TYPE00) / sizeof (UINT32), &Pci);
PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
// Skip PCI Bridge and CardBus Bridge
if(IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {
Save = FALSE;
}
// Skip empty Bar
if (Pci.Device.Bar[BarIndex] == 0) {
Save = FALSE;
}
// Skip IO Space
if ((Pci.Device.Bar[BarIndex] != 0) && ((Pci.Device.Bar[BarIndex] & IO_SPACE_INDICATOR) == IO_SPACE_INDICATOR)) {
Save = FALSE;
}
// Skip SPI BAR0 MMIO base address. It's a fixed bar in Skylake.
if ((Bus == 0) && (Device == PCI_DEVICE_NUMBER_PCH_SPI) && (Function == PCI_FUNCTION_NUMBER_PCH_SPI) && (BarIndex == 0)) {
Save = FALSE;
}
return Save;
}
EFI_STATUS
EFIAPI
SaveUnLockedBar (
VOID
)
{
EFI_STATUS Status;
UINTN Index;
UINTN BarIndex;
UINTN NoHandles;
EFI_HANDLE Handle;
EFI_HANDLE *HandleBuffer;
EFI_PCI_IO_PROTOCOL *PciIo;
PCI_TYPE00 Pci;
UINTN Segment;
UINTN Bus;
UINTN Device;
UINTN Function;
UINTN DynamicBarCount;
DEVICE_BASE_ADDRESS *DynamicBar;
//
// Note: Fixed BARs are platform dependent.
//
DEVICE_BASE_ADDRESS FixedBar[] = {
{0, PCI_DEVICE_NUMBER_PCH_PMC , PCI_FUNCTION_NUMBER_PCH_PMC , R_PCH_PMC_ACPI_BASE , 0}, // ACPI BASE
{0, PCI_DEVICE_NUMBER_PCH_PMC , PCI_FUNCTION_NUMBER_PCH_PMC , R_PCH_PMC_PWRM_BASE , 0}, // PMC MBAR MMIO base address
{0, PCI_DEVICE_NUMBER_PCH_SPI , PCI_FUNCTION_NUMBER_PCH_SPI , R_SPI_CFG_BAR0 , 0} // SPI BAR0 MMIO base address
};
Handle = NULL;
DynamicBar = NULL;
DynamicBarCount = 0;
//
// Save Fixed BARs
//
for (Index = 0; Index < (sizeof(FixedBar)/sizeof(DEVICE_BASE_ADDRESS)); Index++) {
FixedBar[Index].Bar = MmioRead32 (
MmPciAddress (
0,
FixedBar[Index].Bus,
FixedBar[Index].Dev,
FixedBar[Index].Func,
FixedBar[Index].Offset
)
);
}
Status = mSmmVariable->SmmSetVariable (
FIXED_BAR_VARIABLE_NAME,
&gSaveUnLockedBarVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(FixedBar),
FixedBar
);
ASSERT_EFI_ERROR (Status);
///
/// Get Dynamic bar via PciIo
///
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiPciIoProtocolGuid,
NULL,
&NoHandles,
&HandleBuffer
);
ASSERT_EFI_ERROR (Status);
if (!EFI_ERROR (Status)) {
Status = gBS->AllocatePool (
EfiBootServicesData,
NoHandles * sizeof (DEVICE_BASE_ADDRESS) * PCI_MAX_BAR,
&DynamicBar
);
ASSERT_EFI_ERROR (Status);
for (Index = 0; Index < NoHandles; Index++) {
Status = gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiPciIoProtocolGuid,
&PciIo
);
if (EFI_ERROR (Status)) {
continue;
}
PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (PCI_TYPE00) / sizeof (UINT32), &Pci);
PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {
if (IsSaveDynamicBar(PciIo, BarIndex)) {
DynamicBar[DynamicBarCount].Bus = (UINT8)Bus;
DynamicBar[DynamicBarCount].Dev = (UINT8)Device;
DynamicBar[DynamicBarCount].Func = (UINT8)Function;
DynamicBar[DynamicBarCount].Offset = (UINT8) (PCI_BASE_ADDRESSREG_OFFSET + BarIndex * 4);
DynamicBar[DynamicBarCount].Bar = Pci.Device.Bar[BarIndex];
DynamicBarCount++;
}
}
}
}
//
// Save Dynamic BARs
//
Status = mSmmVariable->SmmSetVariable (
DYNAMIC_BAR_VARIABLE_NAME,
&gSaveUnLockedBarVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
DynamicBarCount * sizeof(DEVICE_BASE_ADDRESS),
DynamicBar
);
ASSERT_EFI_ERROR (Status);
Status = gSmst->SmmInstallProtocolInterface (
&Handle,
&gSaveUnlockedBarDoneProtocolGuid,
EFI_NATIVE_INTERFACE,
NULL
);
ASSERT_EFI_ERROR (Status);
if (HandleBuffer != NULL) {
gBS->FreePool (HandleBuffer);
}
if (DynamicBar != NULL) {
gBS->FreePool (DynamicBar);
}
return EFI_SUCCESS;
}