summaryrefslogtreecommitdiff
path: root/ReferenceCode/Chipset/SystemAgent/PciHostBridge
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /ReferenceCode/Chipset/SystemAgent/PciHostBridge
downloadzprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'ReferenceCode/Chipset/SystemAgent/PciHostBridge')
-rw-r--r--ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.c1414
-rw-r--r--ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.cif15
-rw-r--r--ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.dxs43
-rw-r--r--ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.h234
-rw-r--r--ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.inf86
-rw-r--r--ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.mak67
-rw-r--r--ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.sdl41
-rw-r--r--ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciRootBridge.h156
-rw-r--r--ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciRootBridgeIo.c1515
9 files changed, 3571 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.c b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.c
new file mode 100644
index 0000000..e660935
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.c
@@ -0,0 +1,1414 @@
+/** @file
+ Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#include "Token.h" // <<< AMI_OVERRIDE
+#include "PciHostBridge.h"
+#include "PciRootBridge.h"
+#include "PchAccess.h" // <<< AMI_OVERRIDE - EIP# 42483 - Support for Multi-Monitor >>>
+#ifndef GUID_VARIABLE_DECLARATION // AMI_OVERRIDE ... EIP#42483: MemCeiling support <<>>
+#define GUID_VARIABLE_DECLARATION(Variable, Guid) extern EFI_GUID Variable
+#endif
+#include <Protocol\NBMemInfo.h> // AMI_OVERRIDE ... EIP#42483: MemCeiling support <<>>
+///
+/// Support 64 K IO space
+/// Moving RES_IO_BASE due to new ACPI Base address 0x1800
+///
+#define RES_IO_BASE 0x2000
+#define RES_IO_LIMIT 0xFFFF
+
+///
+/// Support 4G address space
+///
+#define RES_MEM_LIMIT_1 ((UINTN) MmPciAddress (0,0,0,0,0) - 1)
+
+///
+/// Hard code: Root Bridge Number within the host bridge
+/// Root Bridge's attribute
+/// Root Bridge's device path
+/// Root Bridge's resource aperture
+///
+static UINTN RootBridgeNumber[1] = { 1 };
+///
+/// Hard code EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM 0 to support prefetchable memory allocation
+///
+#ifdef AMI_COMBINE_MEM_PMEM_FLAG
+static UINT64 RootBridgeAttribute[1][1] = { EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM };
+#else // AMI_COMBINE_MEM_PMEM_FLAG
+static UINT64 RootBridgeAttribute[1][1] = { 0 };
+#endif // AMI_COMBINE_MEM_PMEM_FLAG
+static EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[1][1] = {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8),
+ EISA_PNP_ID(0x0A03),
+ 0,
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+};
+
+static PCI_ROOT_BRIDGE_RESOURCE_APERTURE mResAperture[1][1] = { { 0, ((UINT8)((PCIEX_LENGTH >> 20) - 1)), 0, 0xffffffff, 0, 1 << 16 } }; // <<< AMI_OVERRIDE
+static EFI_HANDLE mDriverImageHandle;
+CHAR16 gMemoryCeilingVariable[] = L"MemCeil."; // AMI_OVERRIDE ... EIP#42483: MemCeiling support <<>>
+EFI_GUID gEfiNbMrcS3DataGuid = EFI_NB_MRC_S3_DATA_GUID; // AMI_OVERRIDE ... EIP#42483: MemCeiling support <<>>
+
+// AMI_OVERRIDE ... Fixed GenericSio use 0x0 ~ 0xfff issue start.
+// It will Override CoreAllocateIoSpace.
+static EFI_ALLOCATE_IO_SPACE gAmiCoreAllocateIoSpace;
+
+EFI_STATUS
+NbCspOverrideCoreAllocateIoSpace (
+ IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
+ IN EFI_GCD_IO_TYPE GcdIoType,
+ IN UINTN Alignment,
+ IN UINT64 Length,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE DeviceHandle OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_GCD_IO_SPACE_DESCRIPTOR IoDescriptor;
+
+ if (GcdIoType == EfiGcdIoTypeIo && *BaseAddress < RES_IO_BASE)
+ {
+ if(GcdAllocateType == EfiGcdAllocateAddress)
+ {
+ Status = gDS->GetIoSpaceDescriptor(*BaseAddress, &IoDescriptor);
+ if(!EFI_ERROR(Status))
+ {
+ if(IoDescriptor.GcdIoType == EfiGcdIoTypeNonExistent)
+ {
+ Status = gDS->AddIoSpace (
+ EfiGcdIoTypeIo,
+ *BaseAddress,
+ Length
+ );
+// ASSERT_EFI_ERROR (Status);
+ }
+ }
+ }
+ }
+
+ return gAmiCoreAllocateIoSpace (
+ GcdAllocateType,
+ GcdIoType,
+ Alignment,
+ Length,
+ BaseAddress,
+ ImageHandle,
+ DeviceHandle
+ );
+}
+// AMI_OVERRIDE ... Fixed GenericSio use 0x0 ~ 0xfff issue end.
+
+//AMI_OVERRIDE START // AMI_OVERRIDE ... EIP#42483: MemCeiling support ...Start...
+EFI_STATUS
+HbCspAdjustMemoryMmioOverlap (
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance
+ )
+{
+ EFI_STATUS Status;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
+ UINTN NumberOfDescriptors;
+ PCI_RES_NODE res;
+ UINTN i;
+ EFI_PHYSICAL_ADDRESS Highest4GMem = 0;
+ EFI_PHYSICAL_ADDRESS LowestMMIO = 0xffffffff;
+ EFI_PHYSICAL_ADDRESS LowestAllocMMIO = 0xffffffff;
+ UINTN MemoryCeiling = 0; //Init to zero incase variable doesn't exist.
+ UINTN NewMemoryCeiling = 0xffffffff;
+ UINTN DataSize = sizeof(UINT32);
+ EFI_PHYSICAL_ADDRESS NeededBottomMmio;
+ UINT32 Attributes = 0; // [ EIP167027 ]
+
+//------------------------------------
+ //Status = gRT->GetVariable ( // [ EIP167027 ]
+ // gMemoryCeilingVariable,
+ // &gEfiNbMrcS3DataGuid,
+ // NULL,
+ // &DataSize,
+ // &MemoryCeiling );
+ Status = gRT->GetVariable (
+ gMemoryCeilingVariable,
+ &gEfiNbMrcS3DataGuid,
+ &Attributes,
+ &DataSize,
+ &MemoryCeiling );
+
+ DEBUG((-1, "OEM trace - GetVariable MemCeil Status = %r\n", Status));
+
+ if (EFI_ERROR(Status))
+ Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS;
+
+ if (Status == EFI_NOT_FOUND) {
+ //Status = gRT->GetVariable ( // [ EIP167027 ]
+ // gMemoryCeilingVariable,
+ // &gEfiGlobalVariableGuid,
+ // NULL,
+ // &DataSize,
+ // &MemoryCeiling
+ // );
+ Status = gRT->GetVariable (
+ gMemoryCeilingVariable,
+ &gEfiGlobalVariableGuid,
+ &Attributes,
+ &DataSize,
+ &MemoryCeiling
+ );
+
+ if (!EFI_ERROR(Status)) {
+ //gRT->SetVariable ( // [ EIP167027 ]
+ // gMemoryCeilingVariable,
+ // &gEfiNbMrcS3DataGuid,
+ // EFI_VARIABLE_NON_VOLATILE
+ // + EFI_VARIABLE_BOOTSERVICE_ACCESS
+ // + EFI_VARIABLE_RUNTIME_ACCESS,
+ // DataSize,
+ // &MemoryCeiling
+ //);
+ gRT->SetVariable (
+ gMemoryCeilingVariable,
+ &gEfiNbMrcS3DataGuid,
+ Attributes,
+ DataSize,
+ &MemoryCeiling
+ );
+ }
+ else
+ Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS;
+ }
+
+ //Memory sizing uses memory ceiling to set top of memory.
+
+ Status = gDS->GetMemorySpaceMap(&NumberOfDescriptors, &MemorySpaceMap);
+ ASSERT_EFI_ERROR(Status);
+
+ //Find the lowest MMIO and lowest allocated MMIO in GCD.
+ for(i = 0; i < NumberOfDescriptors; ++i) {
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descr = &MemorySpaceMap[i];
+ EFI_PHYSICAL_ADDRESS Base = Descr->BaseAddress;
+ //Find highest system below 4GB memory.
+ //Treat any non MMIO as system memory. Not all system memory is reported as system memory,
+ //such as SMM.
+ if (Descr->GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo && Base < LowestMMIO) {
+ EFI_PHYSICAL_ADDRESS EndMem = Base + Descr->Length - 1;
+ if (EndMem > Highest4GMem && EndMem <= 0xffffffff) Highest4GMem = EndMem;
+
+ //Find Lowest mmio above system memory.
+ } else if (Descr->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {
+ if (Base >= 0x100000) {
+ if (Base < LowestMMIO) LowestMMIO = Base;
+ //If ImageHandle, then MMIO is allocated.
+ if (Base < LowestAllocMMIO && Descr->ImageHandle) LowestAllocMMIO = Base;
+ }
+ }
+ }
+
+ (gBS->FreePool)(MemorySpaceMap);
+
+ if (Highest4GMem + 1 != LowestMMIO) {
+ DEBUG((-1, "PciHostCSHooks: System Memory and MMIO are not consequitive.\n Top of Below 4G Memory: %lX\n Bottom of MMIO: %x%x\n",
+ Highest4GMem, LowestMMIO ));
+ }
+
+ //Find any MMIO that could not be allocated due to small of MMIO region.
+ NeededBottomMmio = LowestAllocMMIO;
+ for(i = 0; i < TypeMax; ++i) {
+
+ res=RootBridgeInstance->ResAllocNode[i];
+ if ((res.Type == TypeMem32 && (res.Status != ResNone) && (res.Status != ResAllocated)) ||
+ (res.Type == TypePMem32 && (res.Status != ResNone) && (res.Status != ResAllocated))) {
+ //Determine new memory ceiling variable needed to allocate this memory.
+ NeededBottomMmio = NeededBottomMmio - res.Length;
+ NeededBottomMmio &= ~(res.Alignment);
+ if (NeededBottomMmio < NewMemoryCeiling) NewMemoryCeiling = (UINTN) NeededBottomMmio;
+ }
+ }
+
+ if (NewMemoryCeiling < 0xffffffff) { //Check if a NewMemory Ceiling is needed.
+
+ // Adjust the granularity
+ NewMemoryCeiling &= (~(TOP_LOW_MEM_GRANULARITY - 1));
+
+ if (MemoryCeiling == NewMemoryCeiling) return EFI_SUCCESS; //No change in system configuration. Nothing more to do. Just exit.
+
+ // Change in system config, so MMIO requirement changed. Update MemCeil and do reset.
+ // Set memory ceiling variable.
+ //gRT->SetVariable( // [ EIP167027 ]
+ // gMemoryCeilingVariable,
+ // &gEfiNbMrcS3DataGuid,
+ // EFI_VARIABLE_NON_VOLATILE
+ // + EFI_VARIABLE_BOOTSERVICE_ACCESS
+ // + EFI_VARIABLE_RUNTIME_ACCESS,
+ // DataSize,
+ // &NewMemoryCeiling
+ //);
+ gRT->SetVariable(
+ gMemoryCeilingVariable,
+ &gEfiNbMrcS3DataGuid,
+ Attributes,
+ DataSize,
+ &NewMemoryCeiling
+ );
+
+ DEBUG((-1, "Adjusting maximum top of RAM.\n Resetting System.\n"));
+
+#if (NV_SIMULATION != 1)
+ //Reset only needed of type of physical memory overlaps with MMIO.
+ gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+#endif
+
+ }
+
+ return Status;
+}
+//AMI_OVERRIDE ... // AMI_OVERRIDE ... EIP#42483: MemCeiling support ...END...
+
+EFI_DRIVER_ENTRY_POINT (PciHostBridgeEntryPoint)
+///
+/// Implementation
+///
+/**
+ Entry point of this driver
+
+ @param[in] ImageHandle -
+ @param[in] SystemTable -
+
+ @retval EFI_SUCCESS - Driver Start OK
+ @retval EFI_DEVICE_ERROR - Fail to install PCI_ROOT_BRIDGE_IO protocol.
+**/
+EFI_STATUS
+EFIAPI
+PciHostBridgeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINTN Loop1;
+ UINTN Loop2;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridge;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ EFI_PHYSICAL_ADDRESS PciBaseAddress;
+ EFI_PHYSICAL_ADDRESS RemapBase;
+ EFI_PHYSICAL_ADDRESS RemapLimit;
+ EFI_PHYSICAL_ADDRESS MeSegMask;
+ EFI_PHYSICAL_ADDRESS MeStolenSize;
+ BOOLEAN MeStolenEnable;
+ UINT32 Tolud;
+ UINT64 Length;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ CPU_FAMILY CpuFamilyId;
+ CPU_STEPPING CpuSteppingId;
+#ifndef AMI_OVERRIDE_FOR_REMAP_DISABLED
+ EFI_PHYSICAL_ADDRESS MeStolenBase;
+#endif // AMI_OVERRIDE_FOR_REMAP_DISABLED
+
+ INITIALIZE_SCRIPT (ImageHandle, SystemTable);
+
+ mDriverImageHandle = ImageHandle;
+
+ ///
+ /// This system has one Host Bridge (one Root Bridge in this Host Bridge)
+ ///
+ ///
+ /// Create Host Bridge Device Handle
+ ///
+ for (Loop1 = 0; Loop1 < HOST_BRIDGE_NUMBER; Loop1++) {
+ Status = (gBS->AllocatePool) (EfiBootServicesData, sizeof (PCI_HOST_BRIDGE_INSTANCE), (VOID **) &HostBridge);
+ ASSERT (!EFI_ERROR (Status));
+
+ HostBridge->Signature = PCI_HOST_BRIDGE_SIGNATURE;
+ HostBridge->RootBridgeNumber = RootBridgeNumber[Loop1];
+ HostBridge->ResourceSubmited = FALSE;
+ HostBridge->CanRestarted = TRUE;
+
+ ///
+ /// InitializeListHead (&HostBridge->Head);
+ ///
+ HostBridge->ResAlloc.NotifyPhase = NotifyPhase;
+ HostBridge->ResAlloc.GetNextRootBridge = GetNextRootBridge;
+ HostBridge->ResAlloc.GetAllocAttributes = GetAttributes;
+ HostBridge->ResAlloc.StartBusEnumeration = StartBusEnumeration;
+ HostBridge->ResAlloc.SetBusNumbers = SetBusNumbers;
+ HostBridge->ResAlloc.SubmitResources = SubmitResources;
+ HostBridge->ResAlloc.GetProposedResources = GetProposedResources;
+ HostBridge->ResAlloc.PreprocessController = PreprocessController;
+ HostBridge->HostBridgeHandle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &HostBridge->HostBridgeHandle,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &HostBridge->ResAlloc
+ );
+ if (EFI_ERROR (Status)) {
+ (gBS->FreePool) (HostBridge);
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Create Root Bridge Device Handle in this Host Bridge
+ ///
+ InitializeListHead (&HostBridge->Head);
+ for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) {
+ Status = (gBS->AllocatePool) (EfiBootServicesData, sizeof (PCI_ROOT_BRIDGE_INSTANCE), (VOID **) &PrivateData);
+ ASSERT (!EFI_ERROR (Status));
+
+ PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
+ PrivateData->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &mEfiPciRootBridgeDevicePath[Loop1][Loop2];
+ RootBridgeConstructor (
+ &PrivateData->Io,
+ HostBridge->HostBridgeHandle,
+ RootBridgeAttribute[Loop1][Loop2],
+ &mResAperture[Loop1][Loop2]
+ );
+ PrivateData->Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &PrivateData->Handle,
+ &gEfiDevicePathProtocolGuid,
+ PrivateData->DevicePath,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ &PrivateData->Io,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ (gBS->FreePool) (PrivateData);
+ return EFI_DEVICE_ERROR;
+ }
+
+ InsertTailList (&HostBridge->Head, &PrivateData->Link);
+ }
+ }
+ ///
+ /// Allocate 60 KB of I/O space [0x1000..0xFFFF]
+ ///
+ Status = gDS->AddIoSpace (
+ EfiGcdIoTypeIo,
+ RES_IO_BASE,
+ RES_IO_LIMIT - RES_IO_BASE + 1
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ // AMI_OVERRIDE ... Fixed GenericSio use 0x0 ~ 0xfff issue start.
+ // It will Override CoreAllocateIoSpace.
+ gAmiCoreAllocateIoSpace = gDS->AllocateIoSpace;
+ gDS->AllocateIoSpace = NbCspOverrideCoreAllocateIoSpace;
+ // AMI_OVERRIDE ... Fixed GenericSio use 0x0 ~ 0xfff issue end.
+
+ ///
+ /// Allocate PCI memory space.
+ ///
+ ///
+ /// Read memory map registers
+ ///
+ RemapBase = McD0PciCfg64 (R_SA_REMAPBASE) & B_SA_REMAPBASE_REMAPBASE_MASK;
+ RemapLimit = McD0PciCfg64 (R_SA_REMAPLIMIT) & B_SA_REMAPLIMIT_REMAPLMT_MASK;
+ Tolud = McD0PciCfg32 (R_SA_TOLUD) & B_SA_TOLUD_TOLUD_MASK;
+ PciBaseAddress = Tolud;
+ MeSegMask = McD0PciCfg64 (R_SA_MESEG_MASK);
+ MeStolenEnable = (BOOLEAN) ((MeSegMask & B_SA_MESEG_MASK_ME_STLEN_EN_MASK) != 0);
+
+ ///
+ /// First check if memory remap is used
+ ///
+ if ((RemapBase > RemapLimit) && (MeStolenEnable)) {
+ MeStolenSize = MeSegMask & B_SA_MESEG_MASK_MEMASK_MASK;
+ if (MeStolenSize != 0) {
+ MeStolenSize = 0x8000000000L - MeStolenSize;
+#ifndef AMI_OVERRIDE_FOR_REMAP_DISABLED
+ // Remap is disabled -> if Me Stolen Base on PCI resume, PCI resume - MeStolenSize.
+ MeStolenBase = McD0PciCfg64 (R_SA_MESEG_BASE);
+ if(MeStolenBase < RES_MEM_LIMIT_1) {
+ //
+ // Remap is disabled -> PCI starts at TOLUD + ME Stolen size
+ //
+ PciBaseAddress += MeStolenSize;
+ }
+#endif // AMI_OVERRIDE_FOR_REMAP_DISABLED
+ }
+ ///
+ /// Remap is disabled -> PCI starts at TOLUD + ME Stolen size
+ ///
+#ifdef AMI_OVERRIDE_FOR_REMAP_DISABLED
+ PciBaseAddress += MeStolenSize;
+#endif // AMI_OVERRIDE_FOR_REMAP_DISABLED
+ }
+
+ Length = RES_MEM_LIMIT_1 - PciBaseAddress + 1;
+
+ if (Length != 0) {
+ DEBUG (
+ (
+ EFI_D_INFO, " Allocating PCI space from 0x%X to 0x%X\n", (UINT32) PciBaseAddress, (UINT32)
+ (PciBaseAddress + Length - 1)
+ )
+ );
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ PciBaseAddress,
+ Length,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ ///
+ /// Get CPU Family and Stepping ID
+ ///
+ CpuFamilyId = GetCpuFamily();
+ CpuSteppingId = GetCpuStepping();
+
+ ///
+ /// WA for HSW A0. To exclude the ranges 20000000-201FFFFF (2MB) and 0x40004000-0x40004FFF (4KB).
+ ///
+ if ((CpuFamilyId == EnumCpuHsw) && (CpuSteppingId == EnumHswA0)) {
+ if (McD0PciCfg32 (R_SA_DEVEN) & B_SA_DEVEN_D2EN_MASK) {
+ BaseAddress = 0x20000000;
+ Status = (gBS->AllocatePages) (AllocateAddress, EfiReservedMemoryType, EFI_SIZE_TO_PAGES (0x00200000), &BaseAddress);
+
+ BaseAddress = 0x40004000;
+ Status = (gBS->AllocatePages) (AllocateAddress, EfiReservedMemoryType, EFI_SIZE_TO_PAGES (0x00001000), &BaseAddress);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Enter a certain phase of the PCI enumeration process
+
+ @param[in] This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance
+ @param[in] Phase - The phase during enumeration
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_INVALID_PARAMETER - Wrong phase parameter passed in.
+ @retval EFI_NOT_READY - Resources have not been submitted yet.
+**/
+EFI_STATUS
+EFIAPI
+NotifyPhase (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ PCI_RESOURCE_TYPE Index;
+ LIST_ENTRY *List;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 AddrLen;
+ UINTN BitsOfAlignment;
+ UINT64 Alignment;
+ EFI_STATUS Status;
+ EFI_STATUS ReturnStatus;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ switch (Phase) {
+ case EfiPciHostBridgeBeginEnumeration:
+ if (HostBridgeInstance->CanRestarted) {
+ ///
+ /// Reset the Each Root Bridge
+ ///
+ List = HostBridgeInstance->Head.ForwardLink;
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ for (Index = TypeIo; Index < TypeMax; Index++) {
+ RootBridgeInstance->ResAllocNode[Index].Type = Index;
+ RootBridgeInstance->ResAllocNode[Index].Base = 0;
+ RootBridgeInstance->ResAllocNode[Index].Length = 0;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ HostBridgeInstance->ResourceSubmited = FALSE;
+ HostBridgeInstance->CanRestarted = TRUE;
+ } else {
+ ///
+ /// Can not restart
+ ///
+ return EFI_NOT_READY;
+ }
+ break;
+
+ case EfiPciHostBridgeBeginBusAllocation:
+ ///
+ /// No specific action is required here, can perform any chipset specific programing
+ ///
+ HostBridgeInstance->CanRestarted = FALSE;
+ return EFI_SUCCESS;
+ break;
+
+ case EfiPciHostBridgeEndBusAllocation:
+ ///
+ /// No specific action is required here, can perform any chipset specific programing
+ ///
+ return EFI_SUCCESS;
+ break;
+
+ case EfiPciHostBridgeBeginResourceAllocation:
+ ///
+ /// No specific action is required here, can perform any chipset specific programing
+ ///
+ return EFI_SUCCESS;
+ break;
+
+ case EfiPciHostBridgeAllocateResources:
+ ReturnStatus = EFI_SUCCESS;
+ if (HostBridgeInstance->ResourceSubmited) {
+ ///
+ /// Take care of the resource dependencies between the root bridges
+ ///
+ List = HostBridgeInstance->Head.ForwardLink;
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+
+ Status = HbCspAdjustMemoryMmioOverlap(RootBridgeInstance); // <<< AMI_OVERRIDE - EIP# 42483 - Support for Multi-Monitor >>>
+
+ for (Index = TypeIo; Index < TypeBus; Index++) {
+ if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
+ AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ Alignment = RootBridgeInstance->ResAllocNode[Index].Alignment;
+
+ ///
+ /// Get the number of '1' in Alignment.
+ ///
+ for (BitsOfAlignment = 0; Alignment != 0; BitsOfAlignment++) {
+ Alignment = RShiftU64 (Alignment, 1);
+ }
+
+ switch (Index) {
+ case TypeIo:
+ ///
+ /// It is impossible for this chipset to align 0xFFFF for IO16
+ /// So clear it
+ ///
+ if (BitsOfAlignment >= 16) {
+ BitsOfAlignment = 0;
+ }
+
+#ifndef AMI_ORIGINAL_FOR_MMIO_4G_TOLUD
+ // Support MaxAddressSearchTopDown for Gcd Io
+ BaseAddress = 0xFFFF;
+#endif // AMI_ORIGINAL_FOR_MMIO_4G_TOLUD
+
+ Status = gDS->AllocateIoSpace (
+#ifdef AMI_ORIGINAL_FOR_MMIO_4G_TOLUD
+ EfiGcdAllocateAnySearchBottomUp,
+#else // AMI_ORIGINAL_FOR_MMIO_4G_TOLUD
+ EfiGcdAllocateMaxAddressSearchTopDown,
+#endif // AMI_ORIGINAL_FOR_MMIO_4G_TOLUD
+ EfiGcdIoTypeIo,
+ BitsOfAlignment,
+ AddrLen,
+ &BaseAddress,
+ mDriverImageHandle,
+ NULL
+ );
+ if (!EFI_ERROR (Status)) {
+ RootBridgeInstance->ResAllocNode[Index].Base = (UINTN) BaseAddress;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
+ } else {
+ ///
+ /// Not able to allocate enough I/O memory - critical stop
+ ///
+ DEBUG ((EFI_D_ERROR, "Out of I/O space! AllocateIoSpace() returned %r\n", Status));
+ DEBUG ((EFI_D_ERROR, "Size requested: 0x%lX bytes\n", AddrLen));
+ ReturnStatus = Status;
+ }
+ break;
+
+ case TypeMem32:
+ case TypePMem32:
+ ///
+ /// It is impossible for this chipset to align 0xFFFFFFFF for Mem32
+ /// So clear it
+ ///
+ if (BitsOfAlignment >= 32) {
+ BitsOfAlignment = 0;
+ }
+
+#ifndef AMI_ORIGINAL_FOR_MMIO_4G_TOLUD
+ // Support MMIO 4G to Tolud for EfiGcdAllocateMaxAddressSearchTopDown
+ BaseAddress = 0xFFFFFFFF;
+#endif // AMI_ORIGINAL_FOR_MMIO_4G_TOLUD
+ ///
+ /// Fall through to TypeMem64 / TypePMem64...
+ ///
+ case TypeMem64:
+ case TypePMem64:
+ Status = gDS->AllocateMemorySpace (
+#ifdef AMI_ORIGINAL_FOR_MMIO_4G_TOLUD
+ EfiGcdAllocateAnySearchBottomUp,
+#else // AMI_ORIGINAL_FOR_MMIO_4G_TOLUD
+ EfiGcdAllocateMaxAddressSearchTopDown,
+#endif // AMI_ORIGINAL_FOR_MMIO_4G_TOLUD
+ EfiGcdMemoryTypeMemoryMappedIo,
+ BitsOfAlignment,
+ AddrLen,
+ &BaseAddress,
+ mDriverImageHandle,
+ NULL
+ );
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// We were able to allocate the PCI memory
+ ///
+ RootBridgeInstance->ResAllocNode[Index].Base = (UINTN) BaseAddress;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
+ } else {
+ ///
+ /// Not able to allocate enough PCI memory - critical stop
+ ///
+ DEBUG ((EFI_D_ERROR, "Out of PCI memory! AllocateMemorySpace() returned %r\n", Status));
+ DEBUG ((EFI_D_ERROR, "Size requested: 0x%lX bytes\n", AddrLen));
+ ReturnStatus = Status;
+ }
+ break;
+ default:
+ break;
+ }
+ ///
+ /// end switch
+ ///
+ }
+ }
+
+ List = List->ForwardLink;
+ }
+
+ return ReturnStatus;
+ } else {
+ return EFI_NOT_READY;
+ }
+ break;
+
+ case EfiPciHostBridgeSetResources:
+ break;
+
+ case EfiPciHostBridgeFreeResources:
+ ReturnStatus = EFI_SUCCESS;
+
+ List = HostBridgeInstance->Head.ForwardLink;
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ for (Index = TypeIo; Index < TypeBus; Index++) {
+ if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
+ AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ BaseAddress = RootBridgeInstance->ResAllocNode[Index].Base;
+ switch (Index) {
+ case TypeIo:
+ Status = gDS->FreeIoSpace (BaseAddress, AddrLen);
+ break;
+
+ case TypeMem32:
+ case TypePMem32:
+ case TypeMem64:
+ case TypePMem64:
+ Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+
+ }
+
+ if (EFI_ERROR (Status)) {
+ ReturnStatus = Status;
+ }
+ ///
+ /// end switch
+ ///
+ RootBridgeInstance->ResAllocNode[Index].Type = Index;
+ RootBridgeInstance->ResAllocNode[Index].Base = 0;
+ RootBridgeInstance->ResAllocNode[Index].Length = 0;
+ RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
+ }
+ }
+
+ List = List->ForwardLink;
+ }
+
+ HostBridgeInstance->ResourceSubmited = FALSE;
+ HostBridgeInstance->CanRestarted = TRUE;
+ return ReturnStatus;
+ break;
+
+ case EfiPciHostBridgeEndResourceAllocation:
+ HostBridgeInstance->CanRestarted = FALSE;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// end switch
+ ///
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the device handle of the next PCI root bridge that is associated with
+ this Host Bridge
+
+ @param[in] This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ @param[in] RootBridgeHandle - Returns the device handle of the next PCI Root Bridge.
+ On input, it holds the RootBridgeHandle returned by the most
+ recent call to GetNextRootBridge().The handle for the first
+ PCI Root Bridge is returned if RootBridgeHandle is NULL on input
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_NOT_FOUND - Next PCI root bridge not found.
+ @retval EFI_INVALID_PARAMETER - Wrong parameter passed in.
+**/
+EFI_STATUS
+EFIAPI
+GetNextRootBridge (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN OUT EFI_HANDLE *RootBridgeHandle
+ )
+{
+ BOOLEAN NoRootBridge;
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+
+ NoRootBridge = TRUE;
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ while (List != &HostBridgeInstance->Head) {
+ NoRootBridge = FALSE;
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (*RootBridgeHandle == NULL) {
+ ///
+ /// Return the first Root Bridge Handle of the Host Bridge
+ ///
+ *RootBridgeHandle = RootBridgeInstance->Handle;
+ return EFI_SUCCESS;
+ } else {
+ if (*RootBridgeHandle == RootBridgeInstance->Handle) {
+ ///
+ /// Get next if have
+ ///
+ List = List->ForwardLink;
+ if (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ *RootBridgeHandle = RootBridgeInstance->Handle;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_FOUND;
+ }
+ }
+ }
+
+ List = List->ForwardLink;
+ }
+ ///
+ /// end while
+ ///
+ if (NoRootBridge) {
+ return EFI_NOT_FOUND;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+}
+
+/**
+ Returns the attributes of a PCI Root Bridge.
+
+ @param[in] This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ @param[in] RootBridgeHandle - The device handle of the PCI Root Bridge
+ that the caller is interested in
+ @param[in] Attributes - The pointer to attributes of the PCI Root Bridge
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_INVALID_PARAMETER - Attributes parameter passed in is NULL or
+ RootBridgeHandle is not an EFI_HANDLE
+ that was returned on a previous call to
+ GetNextRootBridge().
+**/
+EFI_STATUS
+EFIAPI
+GetAttributes (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT UINT64 *Attributes
+ )
+{
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+
+ if (Attributes == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ *Attributes = RootBridgeInstance->RootBridgeAttrib;
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+ ///
+ /// RootBridgeHandle is not an EFI_HANDLE
+ /// that was returned on a previous call to GetNextRootBridge()
+ ///
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ This is the request from the PCI enumerator to set up
+ the specified PCI Root Bridge for bus enumeration process.
+
+ @param[in] This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ @param[in] RootBridgeHandle - The PCI Root Bridge to be set up.
+ @param[in] Configuration - Pointer to the pointer to the PCI bus resource descriptor.
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_OUT_OF_RESOURCES - Not enough pool to be allocated.
+ @retval EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.
+**/
+EFI_STATUS
+EFIAPI
+StartBusEnumeration (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ )
+{
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ VOID *Buffer;
+ UINT8 *Temp;
+ EFI_STATUS Status;
+ UINT64 BusStart;
+ UINT64 BusEnd;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ ///
+ /// Set up the Root Bridge for Bus Enumeration
+ ///
+ BusStart = RootBridgeInstance->BusBase;
+ BusEnd = RootBridgeInstance->BusLimit;
+
+ ///
+ /// Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
+ ///
+ Status = (gBS->AllocatePool) (
+ EfiBootServicesData, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR), &Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Temp = (UINT8 *) Buffer;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->Len = 0x2B;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->GenFlag = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->SpecificFlag = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrSpaceGranularity = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrRangeMin = BusStart;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrRangeMax = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrTranslationOffset = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrLen = BusEnd - BusStart + 1;
+
+ Temp = Temp + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Desc = ACPI_END_TAG_DESCRIPTOR;
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Checksum = 0x0;
+ *Configuration = Buffer;
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ This function programs the PCI Root Bridge hardware so that
+ it decodes the specified PCI bus range
+
+ @param[in] This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ @param[in] RootBridgeHandle - The PCI Root Bridge whose bus range is to be programmed
+ @param[in] Configuration - The pointer to the PCI bus resource descriptor
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_INVALID_PARAMETER - Wrong parameters passed in.
+**/
+EFI_STATUS
+EFIAPI
+SetBusNumbers (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ )
+{
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ UINT8 *Ptr;
+ UINTN BusStart;
+ UINTN BusEnd;
+ UINTN BusLen;
+
+ if (Configuration == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ptr = Configuration;
+
+ ///
+ /// Check the Configuration is valid
+ ///
+ if (*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+ Ptr = Configuration;
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ BusStart = (UINTN) ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->AddrRangeMin;
+ BusLen = (UINTN) ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->AddrLen;
+ BusEnd = BusStart + BusLen - 1;
+ if (BusStart > BusEnd) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BusStart < RootBridgeInstance->BusBase) || (BusEnd > RootBridgeInstance->BusLimit)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Update the Bus Range
+ ///
+ RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart;
+ RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;
+ RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;
+
+ ///
+ /// Program the Root Bridge Hardware
+ ///
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Submits the I/O and memory resource requirements for the specified PCI Root Bridge
+
+ @param[in] This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ @param[in] RootBridgeHandle - The PCI Root Bridge whose I/O and memory resource requirements
+ are being submitted
+ @param[in] Configuration - The pointer to the PCI I/O and PCI memory resource descriptor
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_INVALID_PARAMETER - Wrong parameters passed in.
+**/
+EFI_STATUS
+EFIAPI
+SubmitResources (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ )
+{
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ UINT8 *Temp;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
+ UINT64 AddrLen;
+ UINT64 Alignment;
+
+ ///
+ /// Check the input parameter: Configuration
+ ///
+ if (Configuration == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+ Temp = (UINT8 *) Configuration;
+ while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ }
+
+ if (*Temp != ACPI_END_TAG_DESCRIPTOR) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Temp = (UINT8 *) Configuration;
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+ ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
+
+ ///
+ /// Check address range alignment
+ ///
+ if (ptr->AddrRangeMax >= (UINT64) 0xffffffff ||
+ ptr->AddrRangeMax != (Power2MaxMemory (ptr->AddrRangeMax + 1) - 1)
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (ptr->ResType) {
+ case ACPI_ADDRESS_SPACE_TYPE_MEM:
+ ///
+ /// check the memory resource request is supported by PCI root bridge
+ ///
+ /// Hard code EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM 0 to support prefetchable memory allocation
+ ///
+ if (RootBridgeInstance->RootBridgeAttrib == 0 && ptr->SpecificFlag == 0x06) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AddrLen = (UINT64) ptr->AddrLen;
+ Alignment = (UINT64) ptr->AddrRangeMax;
+ if (ptr->AddrSpaceGranularity == 32) {
+ if ((ptr->SpecificFlag & 0x06) == 0x06) {
+ ///
+ /// Apply from GCD
+ ///
+ RootBridgeInstance->ResAllocNode[TypePMem32].Length = AddrLen;
+ RootBridgeInstance->ResAllocNode[TypePMem32].Alignment = Alignment;
+ RootBridgeInstance->ResAllocNode[TypePMem32].Status = ResRequested;
+ HostBridgeInstance->ResourceSubmited = TRUE;
+
+ } else {
+ RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen;
+ RootBridgeInstance->ResAllocNode[TypeMem32].Alignment = Alignment;
+ RootBridgeInstance->ResAllocNode[TypeMem32].Status = ResRequested;
+ HostBridgeInstance->ResourceSubmited = TRUE;
+ }
+ }
+
+ if (ptr->AddrSpaceGranularity == 64) {
+ if ((ptr->SpecificFlag & 0x06) == 0x06) {
+ RootBridgeInstance->ResAllocNode[TypePMem64].Length = AddrLen;
+ RootBridgeInstance->ResAllocNode[TypePMem64].Alignment = Alignment;
+ RootBridgeInstance->ResAllocNode[TypePMem64].Status = ResSubmitted;
+ HostBridgeInstance->ResourceSubmited = TRUE;
+
+ } else {
+ RootBridgeInstance->ResAllocNode[TypeMem64].Length = AddrLen;
+ RootBridgeInstance->ResAllocNode[TypeMem64].Alignment = Alignment;
+ RootBridgeInstance->ResAllocNode[TypeMem64].Status = ResSubmitted;
+ HostBridgeInstance->ResourceSubmited = TRUE;
+ }
+ }
+ break;
+
+ case ACPI_ADDRESS_SPACE_TYPE_IO:
+ AddrLen = (UINT64) ptr->AddrLen;
+ Alignment = (UINT64) ptr->AddrRangeMax;
+ RootBridgeInstance->ResAllocNode[TypeIo].Length = AddrLen;
+ RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment;
+ RootBridgeInstance->ResAllocNode[TypeIo].Status = ResRequested;
+ HostBridgeInstance->ResourceSubmited = TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ This function returns the proposed resource settings for the specified
+ PCI Root Bridge
+
+ @param[in] This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ @param[in] RootBridgeHandle - The PCI Root Bridge handle
+ @param[in] Configuration - The pointer to the pointer to the PCI I/O
+ and memory resource descriptor
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_OUT_OF_RESOURCES - Not enough pool to be allocated.
+ @retval EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.
+**/
+EFI_STATUS
+EFIAPI
+GetProposedResources (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ )
+{
+ LIST_ENTRY *List;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ UINTN Index;
+ UINTN Number;
+ VOID *Buffer;
+ UINT8 *Temp;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
+ EFI_STATUS Status;
+ UINT64 ResStatus;
+
+ Buffer = NULL;
+ Number = 0;
+
+ ///
+ /// Get the Host Bridge Instance from the resource allocation protocol
+ ///
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ ///
+ /// Enumerate the root bridges in this host bridge
+ ///
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ for (Index = 0; Index < TypeBus; Index++) {
+ if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
+ Number++;
+ }
+ }
+
+ if (Number > 0) {
+ Status = (gBS->AllocatePool)
+ (
+ EfiBootServicesData, Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR), &Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (Buffer, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * Number + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+
+ Temp = Buffer;
+ for (Index = 0; Index < TypeBus; Index++) {
+ if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
+ ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
+ ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;
+ switch (Index) {
+ case TypeIo:
+ ///
+ /// Io
+ ///
+ ptr->Desc = 0x8A;
+ ptr->Len = 0x2B;
+ ptr->ResType = 1;
+ ptr->GenFlag = 0;
+ ptr->SpecificFlag = 0;
+ ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
+ ptr->AddrRangeMax = 0;
+ ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ break;
+
+ case TypeMem32:
+ ///
+ /// Memory 32
+ ///
+ ptr->Desc = 0x8A;
+ ptr->Len = 0x2B;
+ ptr->ResType = 0;
+ ptr->GenFlag = 0;
+ ptr->SpecificFlag = 0;
+ ptr->AddrSpaceGranularity = 32;
+ ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
+ ptr->AddrRangeMax = 0;
+ ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ break;
+
+ case TypePMem32:
+ ///
+ /// Prefetch memory 32
+ ///
+ ptr->Desc = 0x8A;
+ ptr->Len = 0x2B;
+ ptr->ResType = 0;
+ ptr->GenFlag = 0;
+ ptr->SpecificFlag = 6;
+ ptr->AddrSpaceGranularity = 32;
+ ptr->AddrRangeMin = 0;
+ ptr->AddrRangeMax = 0;
+ ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ break;
+
+ case TypeMem64:
+ ///
+ /// Memory 64
+ ///
+ ptr->Desc = 0x8A;
+ ptr->Len = 0x2B;
+ ptr->ResType = 0;
+ ptr->GenFlag = 0;
+ ptr->SpecificFlag = 0;
+ ptr->AddrSpaceGranularity = 64;
+ ptr->AddrRangeMin = 0;
+ ptr->AddrRangeMax = 0;
+ ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ break;
+
+ case TypePMem64:
+ ///
+ /// Prefetch memory 64
+ ///
+ ptr->Desc = 0x8A;
+ ptr->Len = 0x2B;
+ ptr->ResType = 0;
+ ptr->GenFlag = 0;
+ ptr->SpecificFlag = 6;
+ ptr->AddrSpaceGranularity = 64;
+ ptr->AddrRangeMin = 0;
+ ptr->AddrRangeMax = 0;
+ ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+ break;
+ }
+
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ }
+ }
+
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Desc = 0x79;
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Checksum = 0x0;
+ *Configuration = Buffer;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ This function is called for all the PCI controllers that the PCI
+ bus driver finds. Can be used to Preprogram the controller.
+
+ @param[in] This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ @param[in] RootBridgeHandle - The PCI Root Bridge handle
+ @param[in] PciAddress - Address of the controller on the PCI bus
+ @param[in] Phase - The Phase during resource allocation
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.
+**/
+EFI_STATUS
+EFIAPI
+PreprocessController (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ LIST_ENTRY *List;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ List = HostBridgeInstance->Head.ForwardLink;
+
+ ///
+ /// Enumerate the root bridges in this host bridge
+ ///
+ while (List != &HostBridgeInstance->Head) {
+ RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+ if (RootBridgeHandle == RootBridgeInstance->Handle) {
+ return EFI_SUCCESS;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Calculate max memory of power 2
+
+ @param[in] MemoryLength - Input memory length.
+
+ @retval Returned Maximum length.
+**/
+UINT64
+Power2MaxMemory (
+ IN UINT64 MemoryLength
+ )
+{
+ UINT64 Result;
+
+ if (RShiftU64 (MemoryLength, 32)) {
+ Result = LShiftU64 ((UINT64) GetPowerOfTwo64 (RShiftU64 (MemoryLength, 32)), 32);
+ } else {
+ Result = (UINT64) GetPowerOfTwo64 (MemoryLength);
+ }
+
+ return Result;
+}
diff --git a/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.cif b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.cif
new file mode 100644
index 0000000..55f38b5
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.cif
@@ -0,0 +1,15 @@
+<component>
+ name = "PciHostBridge"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Chipset\SystemAgent\PciHostBridge\Dxe\"
+ RefName = "PciHostBridge"
+[files]
+"PciHostBridge.sdl"
+"PciHostBridge.mak"
+"PciHostBridge.c"
+"PciHostBridge.h"
+"PciHostBridge.dxs"
+"PciRootBridgeIo.c"
+"PciRootBridge.h"
+"PciHostBridge.inf"
+<endComponent>
diff --git a/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.dxs b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.dxs
new file mode 100644
index 0000000..87cf509
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.dxs
@@ -0,0 +1,43 @@
+/** @file
+ Dependency expression source file.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains a 'Sample Driver' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may be modified by the user, subject to
+ the additional terms of the license agreement
+
+**/
+
+
+//
+// Common for R8 and R9 codebase
+//
+#include "AutoGen.h"
+#include "DxeDepex.h"
+
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+
+#include EFI_PROTOCOL_DEFINITION (CpuIo)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Metronome)
+#endif
+
+DEPENDENCY_START
+ EFI_CPU_IO_PROTOCOL_GUID AND
+ EFI_METRONOME_ARCH_PROTOCOL_GUID
+DEPENDENCY_END
diff --git a/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.h b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.h
new file mode 100644
index 0000000..d94ff48
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.h
@@ -0,0 +1,234 @@
+/** @file
+ The Header file of the Pci Host Bridge Driver
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#ifndef _PCI_HOST_BRIDGE_H_
+#define _PCI_HOST_BRIDGE_H_
+
+#include "EdkIIGlueDxe.h"
+#include "CpuRegs.h"
+#include "CpuPlatformLib.h"
+
+#include EFI_PROTOCOL_DEFINITION (PciHostBridgeResourceAllocation)
+
+///
+/// Hard code the host bridge number in the platform.
+/// In this chipset, there is only one host bridge.
+///
+#define HOST_BRIDGE_NUMBER 1
+
+#define PCI_HOST_BRIDGE_SIGNATURE EFI_SIGNATURE_32 ('e', 'h', 's', 't')
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE HostBridgeHandle;
+ UINTN RootBridgeNumber;
+ LIST_ENTRY Head;
+ BOOLEAN ResourceSubmited;
+ BOOLEAN CanRestarted;
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL ResAlloc;
+} PCI_HOST_BRIDGE_INSTANCE;
+
+#define INSTANCE_FROM_RESOURCE_ALLOCATION_THIS(a) CR (a, PCI_HOST_BRIDGE_INSTANCE, ResAlloc, PCI_HOST_BRIDGE_SIGNATURE)
+
+///
+/// HostBridge Resource Allocation interface
+///
+/**
+ Enter a certain phase of the PCI enumeration process
+
+ @param[in] This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance
+ @param[in] Phase - The phase during enumeration
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_INVALID_PARAMETER - Wrong phase parameter passed in.
+ @retval EFI_NOT_READY - Resources have not been submitted yet.
+**/
+EFI_STATUS
+EFIAPI
+NotifyPhase (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
+ )
+;
+
+/**
+ Return the device handle of the next PCI root bridge that is associated with
+ this Host Bridge
+
+ @param[in] This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ @param[in] RootBridgeHandle - Returns the device handle of the next PCI Root Bridge.
+ On input, it holds the RootBridgeHandle returned by the most
+ recent call to GetNextRootBridge().The handle for the first
+ PCI Root Bridge is returned if RootBridgeHandle is NULL on input
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_NOT_FOUND - Next PCI root bridge not found.
+ @retval EFI_INVALID_PARAMETER - Wrong parameter passed in.
+**/
+EFI_STATUS
+EFIAPI
+GetNextRootBridge (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN OUT EFI_HANDLE *RootBridgeHandle
+ )
+;
+
+/**
+ Returns the attributes of a PCI Root Bridge.
+
+ @param[in] This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ @param[in] RootBridgeHandle - The device handle of the PCI Root Bridge
+ that the caller is interested in
+ @param[in] Attributes - The pointer to attributes of the PCI Root Bridge
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_INVALID_PARAMETER - Attributes parameter passed in is NULL or
+ RootBridgeHandle is not an EFI_HANDLE
+ that was returned on a previous call to
+ GetNextRootBridge().
+**/
+EFI_STATUS
+EFIAPI
+GetAttributes (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT UINT64 *Attributes
+ )
+;
+
+/**
+ This is the request from the PCI enumerator to set up
+ the specified PCI Root Bridge for bus enumeration process.
+
+ @param[in] This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ @param[in] RootBridgeHandle - The PCI Root Bridge to be set up.
+ @param[in] Configuration - Pointer to the pointer to the PCI bus resource descriptor.
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_OUT_OF_RESOURCES - Not enough pool to be allocated.
+ @retval EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.
+**/
+EFI_STATUS
+EFIAPI
+StartBusEnumeration (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ )
+;
+
+/**
+ This function programs the PCI Root Bridge hardware so that
+ it decodes the specified PCI bus range
+
+ @param[in] This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ @param[in] RootBridgeHandle - The PCI Root Bridge whose bus range is to be programmed
+ @param[in] Configuration - The pointer to the PCI bus resource descriptor
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_INVALID_PARAMETER - Wrong parameters passed in.
+**/
+EFI_STATUS
+EFIAPI
+SetBusNumbers (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ )
+;
+
+/**
+ Submits the I/O and memory resource requirements for the specified PCI Root Bridge
+
+ @param[in] This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ @param[in] RootBridgeHandle - The PCI Root Bridge whose I/O and memory resource requirements
+ are being submitted
+ @param[in] Configuration - The pointer to the PCI I/O and PCI memory resource descriptor
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_INVALID_PARAMETER - Wrong parameters passed in.
+**/
+EFI_STATUS
+EFIAPI
+SubmitResources (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ )
+;
+
+/**
+ This function returns the proposed resource settings for the specified
+ PCI Root Bridge
+
+ @param[in] This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ @param[in] RootBridgeHandle - The PCI Root Bridge handle
+ @param[in] Configuration - The pointer to the pointer to the PCI I/O
+ and memory resource descriptor
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_OUT_OF_RESOURCES - Not enough pool to be allocated.
+ @retval EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.
+**/
+EFI_STATUS
+EFIAPI
+GetProposedResources (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ )
+;
+
+/**
+ This function is called for all the PCI controllers that the PCI
+ bus driver finds. Can be used to Preprogram the controller.
+
+ @param[in] This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ @param[in] RootBridgeHandle - The PCI Root Bridge handle
+ @param[in] PciAddress - Address of the controller on the PCI bus
+ @param[in] Phase - The Phase during resource allocation
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.
+**/
+EFI_STATUS
+EFIAPI
+PreprocessController (
+ IN struct _EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ )
+;
+
+/**
+ Calculate max memory of power 2
+
+ @param[in] MemoryLength - Input memory length.
+
+ @retval Returned Maximum length.
+**/
+UINT64
+Power2MaxMemory (
+ IN UINT64 MemoryLength
+ )
+;
+
+#endif
diff --git a/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.inf b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.inf
new file mode 100644
index 0000000..0c4561c
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.inf
@@ -0,0 +1,86 @@
+## @file
+# Component description file for PciHostBridge module
+# {8D6756B9-E55E-4d6a-A3A5-5E4D72DDF772}
+# 0x8d6756b9, 0xee5e, 0x4d6a, 0xa3, 0xa5, 0x5e, 0x4d, 0x72, 0xdd, 0xf7, 0x72
+#
+#@copyright
+# Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+# This file contains a 'Sample Driver' and is licensed as such
+# under the terms of your license agreement with Intel or your
+# vendor. This file may be modified by the user, subject to
+# the additional terms of the license agreement
+#
+
+[defines]
+BASE_NAME = PciHostBridge
+FILE_GUID = 8D6756B9-E55E-4d6a-A3A5-5E4D72DDF772
+COMPONENT_TYPE = BS_DRIVER
+
+[sources.common]
+ PciHostBridge.h
+ PciHostBridge.c
+ PciRootBridge.h
+ PciRootBridgeIo.c
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGlueDxeDriverEntryPoint.c
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EFI_SOURCE)
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+ $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+
+[libraries.common]
+ ArchProtocolLib
+ EdkFrameworkProtocolLib
+ EfiScriptLib
+ EdkIIGlueBaseLib
+ EdkIIGlueBaseIoLibIntrinsic
+ EdkIIGlueDxeDebugLibReportStatusCode
+ EdkIIGlueDxeReportStatusCodeLib
+ EdkIIGlueUefiBootServicesTableLib
+ EdkIIGlueUefiRuntimeServicesTableLib
+ EdkIIGlueDxeServicesTableLib
+ EdkIIGlueUefiLib
+ CPUIA32LIB
+ EdkIIGlueDxeMemoryAllocationLib
+ EdkProtocolLib
+ CpuPlatformLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT = _ModuleEntryPoint
+ DPX_SOURCE = PciHostBridge.dxs
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=PciHostBridgeEntryPoint \
+ -D __EDKII_GLUE_BASE_LIB__ \
+ -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ -D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_LIB__\
+ -D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+
diff --git a/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.mak b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.mak
new file mode 100644
index 0000000..fe3614c
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.mak
@@ -0,0 +1,67 @@
+#---------------------------------------------------------------------------
+# Create PCI Host Bridge DXE Component
+#---------------------------------------------------------------------------
+EDK : PciHostBridge
+
+PciHostBridge : $(BUILD_DIR)\PciHostBridge.mak PciHostBridgeBin
+
+$(BUILD_DIR)\PciHostBridge.mak : $(PciHostBridge_DIR)\PciHostBridge.cif $(BUILD_RULES)
+ $(CIF2MAK) $(PciHostBridge_DIR)\PciHostBridge.cif $(CIF2MAK_DEFAULTS)
+
+PciHostBridge_INCLUDES=\
+ $(EdkIIGlueLib_INCLUDES)\
+ $(EDK_INCLUDES)\
+ $(PROJECT_CPU_INCLUDES)\
+ $(INTEL_MCH_INCLUDES)\
+ $(INTEL_PCH_INCLUDES)\
+ /IInclude
+
+PciHostBridge_DEFINES =$(MY_DEFINES)\
+ /D "__EDKII_GLUE_MODULE_ENTRY_POINT__=PciHostBridgeEntryPoint" \
+ /D __EDKII_GLUE_BASE_LIB__ \
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_UEFI_LIB__\
+ /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+
+PciHostBridge_LIB_LINKS =\
+ $(ArchProtocolLib)\
+ $(EFISCRIPTLIB)\
+ $(EDKFRAMEWORKPROTOCOLLIB)\
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGlueBaseLib_LIB)\
+!IF "$(x64_BUILD)"=="1"
+ $(EdkIIGlueBaseLibX64_LIB)\
+!ELSE
+ $(EdkIIGlueBaseLibIA32_LIB)\
+!ENDIF
+ $(EdkIIGlueDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueDxeServicesTableLib_LIB)\
+ $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueUefiLib_LIB)\
+ $(EdkIIGlueDxeMemoryAllocationLib_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueUefiRuntimeServicesTableLib_LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB)\
+ $(EDKPROTOCOLLIB)\
+ $(EFIDRIVERLIB)\
+ $(CpuPlatformLib_LIB)\
+ $(PchPlatformDxeLib_LIB)
+
+PciHostBridgeBin : $(PciHostBridge_LIB_LINKS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\PciHostBridge.mak all\
+ GUID=8D6756B9-E55E-4d6a-A3A5-5E4D72DDF772 \
+ ENTRY_POINT=_ModuleEntryPoint \
+ "MY_DEFINES=$(PciHostBridge_DEFINES)"\
+ "MY_INCLUDES=$(PciHostBridge_INCLUDES)"\
+ TYPE=BS_DRIVER \
+ EDKIIModule=DXEDRIVER\
+ DEPEX1=$(PciHostBridge_DIR)\PciHostBridge.dxs\
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX\
+ COMPRESS=1
diff --git a/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.sdl b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.sdl
new file mode 100644
index 0000000..9e2b5b3
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciHostBridge.sdl
@@ -0,0 +1,41 @@
+TOKEN
+ Name = "PciHostBridge_SUPPORT"
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+ Help = "Main switch to enable PciHostBridge support in Project"
+ Token = "AMI_ROOT_BRIDGE_SUPPORT" "=" "0"
+End
+
+TOKEN
+ Name = "TOP_LOW_MEM_GRANULARITY"
+ Value = "0x10000000"
+ Help = "Adjust the MMIO granularity size 256MB."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+MODULE
+ Help = "Includes PciHostBridge.mak to Project"
+ File = "PciHostBridge.mak"
+End
+
+PATH
+ Name = "PciHostBridge_DIR"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\PciHostBridge.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "/D AMI_COMBINE_MEM_PMEM_FLAG"
+ Parent = "GLOBAL_DEFINES"
+ InvokeOrder = AfterParent
+ Token = "COMBINE_MEM_PMEM" "=" "1"
+End \ No newline at end of file
diff --git a/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciRootBridge.h b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciRootBridge.h
new file mode 100644
index 0000000..557755e
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciRootBridge.h
@@ -0,0 +1,156 @@
+/** @file
+ The driver for the host to pci bridge (root bridge).
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+#ifndef _PCI_ROOT_BRIDGE_H_
+#define _PCI_ROOT_BRIDGE_H_
+
+#include "EdkIIGlueDxe.h"
+#include "Acpi.h"
+#include "EfiScriptLib.h"
+#include "SaAccess.h"
+
+///
+/// Driver Consumed Protocol Prototypes
+///
+#include EFI_ARCH_PROTOCOL_DEFINITION (Metronome)
+#include EFI_PROTOCOL_CONSUMER (CpuIo)
+
+///
+/// Driver Produced Protocol Prototypes
+///
+#include EFI_PROTOCOL_DEFINITION (DevicePath)
+#include EFI_PROTOCOL_DEFINITION (PciRootBridgeIo)
+
+///
+/// Define resource status constant
+///
+#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFF
+#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFE
+#define EFI_RESOURCE_SATISFIED 0x0000000000000000
+
+///
+/// Driver Instance Data Prototypes
+///
+typedef struct {
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation;
+ UINTN NumberOfBytes;
+ UINTN NumberOfPages;
+ EFI_PHYSICAL_ADDRESS HostAddress;
+ EFI_PHYSICAL_ADDRESS MappedHostAddress;
+} MAP_INFO;
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+
+typedef struct {
+ UINT64 BusBase;
+ UINT64 BusLimit;
+ UINT64 MemBase;
+ UINT64 MemLimit;
+ UINT64 IoBase;
+ UINT64 IoLimit;
+} PCI_ROOT_BRIDGE_RESOURCE_APERTURE;
+
+typedef enum {
+ TypeIo = 0,
+ TypeMem32,
+ TypePMem32,
+ TypeMem64,
+ TypePMem64,
+ TypeBus,
+ TypeMax
+} PCI_RESOURCE_TYPE;
+
+typedef enum {
+ ResNone = 0,
+ ResSubmitted,
+ ResRequested,
+ ResAllocated,
+ ResStatusMax
+} RES_STATUS;
+
+typedef struct {
+ PCI_RESOURCE_TYPE Type;
+ UINT64 Base;
+ UINT64 Length;
+ UINT64 Alignment;
+ RES_STATUS Status;
+} PCI_RES_NODE;
+
+#define PCI_ROOT_BRIDGE_SIGNATURE EFI_SIGNATURE_32 ('e', '2', 'p', 'b')
+
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ EFI_HANDLE Handle;
+ UINT64 RootBridgeAttrib;
+ UINT64 Attributes;
+ UINT64 Supports;
+
+ ///
+ /// Specific for this memory controller: Bus, I/O, Mem
+ ///
+ PCI_RES_NODE ResAllocNode[6];
+
+ ///
+ /// Addressing for Memory and I/O and Bus arrange
+ ///
+ UINT64 BusBase;
+ UINT64 MemBase;
+ UINT64 IoBase;
+ UINT64 BusLimit;
+ UINT64 MemLimit;
+ UINT64 IoLimit;
+ EFI_LOCK PciLock;
+ UINTN PciAddress;
+ UINTN PciData;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
+} PCI_ROOT_BRIDGE_INSTANCE;
+
+///
+/// Driver Instance Data Macros
+///
+#define DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) CR (a, PCI_ROOT_BRIDGE_INSTANCE, Io, PCI_ROOT_BRIDGE_SIGNATURE)
+
+#define DRIVER_INSTANCE_FROM_LIST_ENTRY(a) CR (a, PCI_ROOT_BRIDGE_INSTANCE, Link, PCI_ROOT_BRIDGE_SIGNATURE)
+
+/**
+ Construct the Pci Root Bridge Io protocol
+
+ @param[in] Protocol - Point to protocol instance
+ @param[in] HostBridgeHandle - Handle of host bridge
+ @param[in] Attri - Attribute of host bridge
+ @param[in] ResAperture - ResourceAperture for host bridge
+
+ @retval EFI_SUCCESS - Success to initialize the Pci Root Bridge.
+**/
+EFI_STATUS
+RootBridgeConstructor (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
+ IN EFI_HANDLE HostBridgeHandle,
+ IN UINT64 Attri,
+ IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE *ResAperture
+ )
+;
+
+#endif
diff --git a/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciRootBridgeIo.c b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciRootBridgeIo.c
new file mode 100644
index 0000000..a3a0447
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/PciHostBridge/Dxe/PciRootBridgeIo.c
@@ -0,0 +1,1515 @@
+/** @file
+ EFI Memory Controller PCI Root Bridge Io Protocol
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#include "PciRootBridge.h"
+#include "Pci22.h"
+
+typedef struct {
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR SpaceDesp[TypeMax];
+ EFI_ACPI_END_TAG_DESCRIPTOR EndDesp;
+} RESOURCE_CONFIGURATION;
+
+RESOURCE_CONFIGURATION Configuration = {
+ {
+ {
+ 0x8A,
+ 0x2B,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ {
+ 0x8A,
+ 0x2B,
+ 0,
+ 0,
+ 0,
+ 32,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ {
+ 0x8A,
+ 0x2B,
+ 0,
+ 0,
+ 6,
+ 32,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ {
+ 0x8A,
+ 0x2B,
+ 0,
+ 0,
+ 0,
+ 64,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ {
+ 0x8A,
+ 0x2B,
+ 0,
+ 0,
+ 6,
+ 64,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ {
+ 0x8A,
+ 0x2B,
+ 2,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ }
+ },
+ {
+ 0x79,
+ 0
+ }
+};
+
+///
+/// Protocol Member Function Prototypes
+///
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoCopyMem (
+ IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ );
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ );
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ );
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ );
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ );
+
+EFI_STATUS
+EFIAPI
+RootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ );
+
+///
+/// Sub Function Prototypes
+///
+typedef union {
+ UINT8 VOLATILE *buf;
+ UINT8 VOLATILE *ui8;
+ UINT16 VOLATILE *ui16;
+ UINT32 VOLATILE *ui32;
+ UINT64 VOLATILE *ui64;
+ UINTN VOLATILE ui;
+} PTR;
+
+STATIC
+EFI_STATUS
+RootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ );
+
+///
+/// Memory Controller Pci Root Bridge Io Module Variables
+///
+EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
+EFI_CPU_IO_PROTOCOL *mCpuIo;
+
+/**
+ Construct the Pci Root Bridge Io protocol
+
+ @param Protocol - Point to protocol instance
+ @param HostBridgeHandle - Handle of host bridge
+ @param Attri - Attribute of host bridge
+ @param ResAperture - ResourceAperture for host bridge
+
+ @retval EFI_SUCCESS - Success to initialize the Pci Root Bridge.
+**/
+EFI_STATUS
+RootBridgeConstructor (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
+ IN EFI_HANDLE HostBridgeHandle,
+ IN UINT64 Attri,
+ IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE *ResAperture
+ )
+{
+ EFI_STATUS Status;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ PCI_RESOURCE_TYPE Index;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol);
+
+ ///
+ /// The host to pci bridge, the host memory and io addresses are
+ /// direct mapped to pci addresses, so no need translate, set bases to 0.
+ ///
+ PrivateData->MemBase = ResAperture->MemBase;
+ PrivateData->IoBase = ResAperture->IoBase;
+
+ ///
+ /// The host bridge only supports 32bit addressing for memory
+ /// and standard IA32 16bit io
+ ///
+ PrivateData->MemLimit = ResAperture->MemLimit;
+ PrivateData->IoLimit = ResAperture->IoLimit;
+
+ ///
+ /// Bus Aperture for this Root Bridge (Possible Range)
+ ///
+ PrivateData->BusBase = ResAperture->BusBase;
+ PrivateData->BusLimit = ResAperture->BusLimit;
+
+ ///
+ /// Specific for this chipset
+ ///
+ for (Index = TypeIo; Index < TypeMax; Index++) {
+ PrivateData->ResAllocNode[Index].Type = Index;
+ PrivateData->ResAllocNode[Index].Base = 0;
+ PrivateData->ResAllocNode[Index].Length = 0;
+ PrivateData->ResAllocNode[Index].Status = ResNone;
+ }
+
+ EfiInitializeLock (&PrivateData->PciLock, EFI_TPL_HIGH_LEVEL);
+ PrivateData->PciAddress = 0xCF8;
+ PrivateData->PciData = 0xCFC;
+ PrivateData->RootBridgeAttrib = Attri;
+ PrivateData->Attributes = 0;
+ ///
+ /// Set both ISA_IO and ISA_IO_16 / VGA_IO and VGA_IO_16 to co-work
+ /// with EDK and EDK2 PCI bus driver.
+ ///
+ PrivateData->Supports = EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO |
+ EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO |
+ EFI_PCI_ATTRIBUTE_ISA_IO |
+ EFI_PCI_ATTRIBUTE_ISA_IO_16 |
+ EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO |
+ EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 |
+ EFI_PCI_ATTRIBUTE_VGA_MEMORY |
+ EFI_PCI_ATTRIBUTE_VGA_IO |
+ EFI_PCI_ATTRIBUTE_VGA_IO_16;
+ Protocol->ParentHandle = HostBridgeHandle;
+ Protocol->PollMem = RootBridgeIoPollMem;
+ Protocol->PollIo = RootBridgeIoPollIo;
+ Protocol->Mem.Read = RootBridgeIoMemRead;
+ Protocol->Mem.Write = RootBridgeIoMemWrite;
+ Protocol->Io.Read = RootBridgeIoIoRead;
+ Protocol->Io.Write = RootBridgeIoIoWrite;
+ Protocol->CopyMem = RootBridgeIoCopyMem;
+ Protocol->Pci.Read = RootBridgeIoPciRead;
+ Protocol->Pci.Write = RootBridgeIoPciWrite;
+ Protocol->Map = RootBridgeIoMap;
+ Protocol->Unmap = RootBridgeIoUnmap;
+ Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer;
+ Protocol->FreeBuffer = RootBridgeIoFreeBuffer;
+ Protocol->Flush = RootBridgeIoFlush;
+ Protocol->GetAttributes = RootBridgeIoGetAttributes;
+ Protocol->SetAttributes = RootBridgeIoSetAttributes;
+ Protocol->Configuration = RootBridgeIoConfiguration;
+ Protocol->SegmentNumber = 0;
+ Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **) &mMetronome);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (&gEfiCpuIoProtocolGuid, NULL, (VOID **) &mCpuIo);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Polls an address in memory mapped I/O space until an exit condition is met, or
+ a timeout occurs.
+
+ @param[in] This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width - Signifies the width of the memory operations.
+ @param[in] Address - The base address of the memory operations. The caller is
+ responsible for aligning Address if required.
+ @param[in] Mask - Mask used for the polling criteria. Bytes above Width in Mask
+ are ignored. The bits in the bytes below Width which are zero in
+ Mask are ignored when polling the memory address.
+ @param[in] Value - The comparison value used for the polling exit criteria.
+ @param[in] Delay - The number of 100 ns units to poll. Note that timer available may
+ be of poorer granularity.
+ @param[out] Result - Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS - The last data returned from the access matched the poll exit criteria.
+ @retval EFI_INVALID_PARAMETER - Width is invalid or Result is NULL..
+ @retval EFI_TIMEOUT - Delay expired before a match occurred.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ EFI_STATUS Status;
+ UINT64 NumberOfTicks;
+ UINT32 Remainder;
+
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// No matter what, always do a single poll.
+ ///
+ Status = This->Mem.Read (This, Width, Address, 1, Result);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ if (Delay == 0) {
+ return EFI_SUCCESS;
+ } else {
+ ///
+ /// Determine the proper # of metronome ticks to wait for polling the
+ /// location. The nuber of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
+ /// The "+1" to account for the possibility of the first tick being short
+ /// because we started in the middle of a tick.
+ ///
+ NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod, &Remainder);
+ if (Remainder != 0) {
+ NumberOfTicks += 1;
+ }
+
+ NumberOfTicks += 1;
+ while (NumberOfTicks) {
+ mMetronome->WaitForTick (mMetronome, 1);
+ Status = This->Mem.Read (This, Width, Address, 1, Result);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks -= 1;
+ }
+ }
+
+ return EFI_TIMEOUT;
+}
+
+/**
+ Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
+ satisfied or after a defined duration.
+
+ @param[in] This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width - Signifies the width of the I/O operations.
+ @param[in] Address - The base address of the I/O operations. The caller is responsible
+ for aligning Address if required.
+ @param[in] Mask - Mask used for the polling criteria. Bytes above Width in Mask
+ are ignored. The bits in the bytes below Width which are zero in
+ Mask are ignored when polling the I/O address.
+ @param[in] Value - The comparison value used for the polling exit criteria.
+ @param[in] Delay - The number of 100 ns units to poll. Note that timer available may
+ be of poorer granularity.
+ @param[out] Result - Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS - The last data returned from the access matched the poll exit criteria.
+ @retval EFI_INVALID_PARAMETER - Width is invalid or Result is NULL.
+ @retval EFI_TIMEOUT - Delay expired before a match occurred.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ EFI_STATUS Status;
+ UINT64 NumberOfTicks;
+ UINT32 Remainder;
+
+ ///
+ /// No matter what, always do a single poll.
+ ///
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = This->Io.Read (This, Width, Address, 1, Result);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ if (Delay == 0) {
+ return EFI_SUCCESS;
+ } else {
+ ///
+ /// Determine the proper # of metronome ticks to wait for polling the
+ /// location. The number of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
+ /// The "+1" to account for the possibility of the first tick being short
+ /// because we started in the middle of a tick.
+ ///
+ NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod, &Remainder);
+ if (Remainder != 0) {
+ NumberOfTicks += 1;
+ }
+
+ NumberOfTicks += 1;
+ while (NumberOfTicks) {
+ mMetronome->WaitForTick (mMetronome, 1);
+ Status = This->Io.Read (This, Width, Address, 1, Result);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks -= 1;
+ }
+ }
+
+ return EFI_TIMEOUT;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param[in] This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width - Signifies the width of the memory operation.
+ @param[in] Address - The base address of the memory operation. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count - The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at Address.
+ @param[in, out] Buffer - For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS - The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER - Width is invalid for this PCI root bridge or Buffer is NULL.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth;
+ UINTN OldCount;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+// AMI_OVERRIDE (EIP#106042+)>>
+ // Fix Fpt.efi not work, accessing Rom decode region could cause AEL bit
+ // be set, and, Pci Resource should not be inside rom decode region.
+ if ((Address >= 0xff000000) && (Address <= 0xffffffff)) {
+ return EFI_INVALID_PARAMETER;
+ }
+// AMI_OVERRIDE <<
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ ///
+ /// Check memory access limit
+ ///
+ if (Address < PrivateData->MemBase) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldWidth = Width;
+ OldCount = Count;
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ Count = 1;
+ }
+
+ Width &= 0x03;
+ if (Address + MultU64x32 (LShiftU64 (1, Width), (UINT32) Count) - 1 > PrivateData->MemLimit) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return mCpuIo->Mem.Read (
+ mCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth,
+ Address,
+ OldCount,
+ Buffer
+ );
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param[in] This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width - Signifies the width of the memory operation.
+ @param[in] Address - The base address of the memory operation. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count - The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at Address.
+ @param[in, out] Buffer - For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS - The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER - Width is invalid for this PCI root bridge or Buffer is NULL.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth;
+ UINTN OldCount;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ ///
+ /// Check memory access limit
+ ///
+ if (Address < PrivateData->MemBase) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldWidth = Width;
+ OldCount = Count;
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ Count = 1;
+ }
+
+ Width &= 0x03;
+ if (Address + MultU64x32 (LShiftU64 (1, Width), (UINT32) Count) - 1 > PrivateData->MemLimit) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return mCpuIo->Mem.Write (
+ mCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth,
+ Address,
+ OldCount,
+ Buffer
+ );
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
+
+ @param[in] This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width - Signifies the width of the memory operations.
+ @param[in] UserAddress - The base address of the I/O operation. The caller is responsible for
+ aligning the Address if required.
+ @param[in] Count - The number of I/O operations to perform. Bytes moved is Width
+ size * Count, starting at Address.
+ @param[in, out] UserBuffer - For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS - The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER - Width is invalid for this PCI root bridge or Buffer is NULL.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+
+ UINTN AlignMask;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth;
+ UINTN OldCount;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ ///
+ /// AlignMask = (1 << Width) - 1;
+ ///
+ AlignMask = (1 << (Width & 0x03)) - 1;
+
+ ///
+ /// Check Io access limit
+ ///
+ if (Address < PrivateData->IoBase) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldWidth = Width;
+ OldCount = Count;
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ Count = 1;
+ }
+
+ Width &= 0x03;
+ if (Address + MultU64x32 (LShiftU64 (1, Width), (UINT32) Count) - 1 >= PrivateData->IoLimit) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return mCpuIo->Io.Read (
+ mCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth,
+ Address,
+ OldCount,
+ Buffer
+ );
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
+
+ @param[in] This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width - Signifies the width of the memory operations.
+ @param[in] UserAddress - The base address of the I/O operation. The caller is responsible for
+ aligning the Address if required.
+ @param[in] Count - The number of I/O operations to perform. Bytes moved is Width
+ size * Count, starting at Address.
+ @param[in, out] UserBuffer - For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS - The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER - Width is invalid for this PCI root bridge or Buffer is NULL.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ UINTN AlignMask;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth;
+ UINTN OldCount;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ ///
+ /// AlignMask = (1 << Width) - 1;
+ ///
+ AlignMask = (1 << (Width & 0x03)) - 1;
+
+ ///
+ /// Check Io access limit
+ ///
+ if (Address < PrivateData->IoBase) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldWidth = Width;
+ OldCount = Count;
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ Count = 1;
+ }
+
+ Width &= 0x03;
+ if (Address + MultU64x32 (LShiftU64 (1, Width), (UINT32) Count) - 1 >= PrivateData->IoLimit) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return mCpuIo->Io.Write (
+ mCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth,
+ Address,
+ OldCount,
+ Buffer
+ );
+}
+
+/**
+ Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI
+ root bridge memory space.
+
+ @param[in] This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ @param[in] Width - Signifies the width of the memory operations.
+ @param[in] DestAddress - The destination address of the memory operation. The caller is
+ responsible for aligning the DestAddress if required.
+ @param[in] SrcAddress - The source address of the memory operation. The caller is
+ responsible for aligning the SrcAddress if required.
+ @param[in] Count - The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at DestAddress and SrcAddress.
+
+ @retval EFI_SUCCESS - The data was copied from one memory region to another memory region.
+ @retval EFI_INVALID_PARAMETER - Width is invalid for this PCI root bridge.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoCopyMem (
+ IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Direction;
+ UINTN Stride;
+ UINTN Index;
+ UINT64 Result;
+
+ if (Width < 0 || Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DestAddress == SrcAddress) {
+ return EFI_SUCCESS;
+ }
+
+ Stride = (UINTN) (LShiftU64 (1, Width));
+ Direction = TRUE;
+ if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
+ Direction = FALSE;
+ SrcAddress = SrcAddress + (Count - 1) * Stride;
+ DestAddress = DestAddress + (Count - 1) * Stride;
+ }
+
+ for (Index = 0; Index < Count; Index++) {
+ Status = RootBridgeIoMemRead (
+ This,
+ Width,
+ SrcAddress,
+ 1,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = RootBridgeIoMemWrite (
+ This,
+ Width,
+ DestAddress,
+ 1,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Direction) {
+ SrcAddress += Stride;
+ DestAddress += Stride;
+ } else {
+ SrcAddress -= Stride;
+ DestAddress -= Stride;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
+
+ @param[in] This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width - Signifies the width of the memory operations.
+ @param[in] Address - The address within the PCI configuration space for the PCI controller.
+ @param[in] Count - The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[in, out] Buffer - For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS - The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER - Width is invalid for this PCI root bridge or Buffer is NULL.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Read Pci configuration space
+ ///
+ return RootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
+
+ @param[in] This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width - Signifies the width of the memory operations.
+ @param[in] Address - The address within the PCI configuration space for the PCI controller.
+ @param[in] Count - The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[in, out] Buffer - For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS - The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER - Width is invalid for this PCI root bridge or Buffer is NULL.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Write Pci configuration space
+ ///
+ return RootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+/**
+ Provides the PCI controller-specific addresses required to access system memory from a
+ DMA bus master.
+
+ @param[in] This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Operation - Indicates if the bus master is going to read or write to system memory.
+ @param[in] HostAddress - The system memory address to map to the PCI controller.
+ @param[in, out] NumberOfBytes - On input the number of bytes to map. On output the number of bytes that were mapped.
+ @param[out] DeviceAddress - The resulting map address for the bus master PCI controller to use
+ to access the system memory's HostAddress.
+ @param[out] Mapping - The value to pass to Unmap() when the bus master DMA operation is complete.
+
+ @retval EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
+ @retval EFI_INVALID_PARAMETER - Operation is invalid.
+ @retval EFI_INVALID_PARAMETER - HostAddress or NumberOfBytes or DeviceAddress or Mapping is NULL.
+ @retval EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common buffer.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+ MAP_INFO *MapInfo;
+
+ if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Initialize the return values to their defaults
+ ///
+ *Mapping = NULL;
+
+ ///
+ /// Make sure that Operation is valid
+ ///
+ if (Operation < 0 || Operation >= EfiPciOperationMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Most PCAT like chipsets can not handle performing DMA above 4GB.
+ /// If any part of the DMA transfer being mapped is above 4GB, then
+ /// map the DMA transfer to a buffer below 4GB.
+ ///
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
+ if ((PhysicalAddress +*NumberOfBytes) > 0x100000000) {
+ ///
+ /// Common Buffer operations can not be remapped. If the common buffer
+ /// if above 4GB, then it is not possible to generate a mapping, so return
+ /// an error.
+ ///
+ if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Allocate a MAP_INFO structure to remember the mapping when Unmap() is
+ /// called later.
+ ///
+ Status = (gBS->AllocatePool) (EfiBootServicesData, sizeof (MAP_INFO), (VOID **) &MapInfo);
+ if (EFI_ERROR (Status)) {
+ *NumberOfBytes = 0;
+ return Status;
+ }
+ ///
+ /// Return a pointer to the MAP_INFO structure in Mapping
+ ///
+ *Mapping = MapInfo;
+
+ ///
+ /// Initialize the MAP_INFO structure
+ ///
+ MapInfo->Operation = Operation;
+ MapInfo->NumberOfBytes = *NumberOfBytes;
+ MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes);
+ MapInfo->HostAddress = PhysicalAddress;
+ MapInfo->MappedHostAddress = 0x00000000ffffffff;
+
+ ///
+ /// Allocate a buffer below 4GB to map the transfer to.
+ ///
+ Status = (gBS->AllocatePages) (AllocateMaxAddress, EfiBootServicesData, MapInfo->NumberOfPages, &MapInfo->MappedHostAddress);
+ if (EFI_ERROR (Status)) {
+ (gBS->FreePool) (MapInfo);
+ *NumberOfBytes = 0;
+ return Status;
+ }
+ ///
+ /// If this is a read operation from the Bus Master's point of view,
+ /// then copy the contents of the real buffer into the mapped buffer
+ /// so the Bus Master can read the contents of the real buffer.
+ ///
+ if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
+ CopyMem (
+ (VOID *) (UINTN) MapInfo->MappedHostAddress,
+ (VOID *) (UINTN) MapInfo->HostAddress,
+ MapInfo->NumberOfBytes
+ );
+ }
+ ///
+ /// The DeviceAddress is the address of the maped buffer below 4GB
+ ///
+ *DeviceAddress = MapInfo->MappedHostAddress;
+ } else {
+ ///
+ /// The transfer is below 4GB, so the DeviceAddress is simply the HostAddress
+ ///
+ *DeviceAddress = PhysicalAddress;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Completes the Map() operation and releases any corresponding resources.
+
+ @param[in] This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Mapping - The mapping value returned from Map().
+
+ @retval EFI_SUCCESS - The range was unmapped.
+ @retval EFI_INVALID_PARAMETER - Mapping is not a value that was returned by Map().
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+{
+ MAP_INFO *MapInfo;
+
+ ///
+ /// See if the Map() operation associated with this Unmap() required a mapping buffer.
+ /// If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
+ ///
+ if (Mapping != NULL) {
+ ///
+ /// Get the MAP_INFO structure from Mapping
+ ///
+ MapInfo = (MAP_INFO *) Mapping;
+
+ ///
+ /// If this is a write operation from the Bus Master's point of view,
+ /// then copy the contents of the mapped buffer into the real buffer
+ /// so the processor can read the contents of the real buffer.
+ ///
+ if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {
+ CopyMem (
+ (VOID *) (UINTN) MapInfo->HostAddress,
+ (VOID *) (UINTN) MapInfo->MappedHostAddress,
+ MapInfo->NumberOfBytes
+ );
+ }
+ ///
+ /// Free the mapped buffer and the MAP_INFO structure.
+ ///
+ (gBS->FreePages) (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
+ (gBS->FreePool) (Mapping);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or
+ EfiPciOperationBusMasterCommonBuffer64 mapping.
+
+ @param This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Type - This parameter is not used and must be ignored.
+ @param MemoryType - The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData.
+ @param Pages - The number of pages to allocate.
+ @param HostAddress - A pointer to store the base system memory address of the allocated range.
+ @param Attributes - The requested bit mask of attributes for the allocated range. Only
+ the attributes EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_ATTRIBUTE_MEMORY_CACHED,
+ and EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this function.
+
+ @retval EFI_SUCCESS - The requested memory pages were allocated.
+ @retval EFI_INVALID_PARAMETER - MemoryType is invalid or HostAddress is NULL.
+ @retval EFI_UNSUPPORTED - Attributes is unsupported. The only legal attribute bits are
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+
+ ///
+ /// Validate Attributes
+ ///
+ if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Check for invalid inputs
+ ///
+ if (HostAddress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ///
+ /// The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
+ ///
+ if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Limit allocations to memory below 4GB
+ ///
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (0xffffffff);
+ Status = (gBS->AllocatePages) (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *HostAddress = (VOID *) (UINTN) PhysicalAddress;
+ return EFI_SUCCESS;
+}
+
+/**
+ Frees memory that was allocated with AllocateBuffer().
+
+ The FreeBuffer() function frees memory that was allocated with AllocateBuffer().
+
+ @param This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Pages - The number of pages to free.
+ @param HostAddress - The base system memory address of the allocated range.
+
+ @retval EFI_SUCCESS - The requested memory pages were freed.
+ @retval EFI_INVALID_PARAMETER - The memory range specified by HostAddress and Pages
+ was not allocated with AllocateBuffer().
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ )
+{
+ return (gBS->FreePages) ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
+}
+
+/**
+ Flushes all PCI posted write transactions from a PCI host bridge to system memory.
+
+ @param This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @retval EFI_SUCCESS - The PCI posted write transactions were flushed from the PCI host
+ bridge to system memory.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ )
+{
+ ///
+ /// not supported yet
+ ///
+ return EFI_SUCCESS;
+}
+
+/**
+ Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the
+ attributes that a PCI root bridge is currently using.
+
+ @param This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Supported - A pointer to the mask of attributes that this PCI root bridge
+ supports setting with SetAttributes().
+ @param Attributes - A pointer to the mask of attributes that this PCI root bridge is
+ currently using.
+
+ @retval EFI_SUCCESS - If Supports is not NULL, then the attributes that the PCI root
+ bridge supports is returned in Supports. If Attributes is
+ not NULL, then the attributes that the PCI root bridge is currently
+ using is returned in Attributes.
+ @retval EFI_INVALID_PARAMETER - Both Supports and Attributes are NULL.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+ if (Attributes == NULL && Supported == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Set the return value for Supported and Attributes
+ ///
+ if (Supported) {
+ *Supported = PrivateData->Supports;
+ }
+
+ if (Attributes) {
+ *Attributes = PrivateData->Attributes;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Sets attributes for a resource range on a PCI root bridge.
+
+ @param[in] This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Attributes - The mask of attributes to set. If the attribute bit
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, or
+ MEMORY_DISABLE is set, then the resource range is specified by
+ ResourceBase and ResourceLength. If
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
+ MEMORY_DISABLE are not set, then ResourceBase and
+ ResourceLength are ignored, and may be NULL.
+ @param[in, out] ResourceBase - A pointer to the base address of the resource range to be modified
+ by the attributes specified by Attributes.
+ @param[in, out] ResourceLength - A pointer to the length of the resource range to be modified by the
+ attributes specified by Attributes.
+
+ @retval EFI_SUCCESS - The current configuration of this PCI root bridge was returned in Resources.
+ @retval EFI_UNSUPPORTED - The current configuration of this PCI root bridge could not be retrieved.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+ if (Attributes) {
+ if ((Attributes & (~(PrivateData->Supports))) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ if (Attributes == PrivateData->Attributes) {
+ return EFI_SUCCESS;
+ }
+ ///
+ /// It is just a trick for some attribute can only be enabled or disabled
+ /// otherwise it can impact on other devices
+ ///
+ PrivateData->Attributes = Attributes;
+ return EFI_SUCCESS;
+}
+
+/**
+ Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0
+ resource descriptors.
+
+ @param[in] This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[out] Resources - A pointer to the ACPI 2.0 resource descriptors that describe the
+ current configuration of this PCI root bridge. The storage for the
+ ACPI 2.0 resource descriptors is allocated by this function. The
+ caller must treat the return buffer as read-only data, and the buffer
+ must not be freed by the caller.
+
+ @retval EFI_SUCCESS - The current configuration of this PCI root bridge was returned in Resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN Index;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+ for (Index = 0; Index < TypeMax; Index++) {
+ if (PrivateData->ResAllocNode[Index].Status == ResAllocated) {
+ Configuration.SpaceDesp[Index].AddrRangeMin = PrivateData->ResAllocNode[Index].Base;
+ Configuration.SpaceDesp[Index].AddrRangeMax = PrivateData->ResAllocNode[Index].Base +
+ PrivateData->ResAllocNode[Index].Length -
+ 1;
+ Configuration.SpaceDesp[Index].AddrLen = PrivateData->ResAllocNode[Index].Length;
+ }
+ }
+
+ *Resources = &Configuration;
+ return EFI_SUCCESS;
+}
+
+/**
+ Internal help function for read and write PCI configuration space.
+
+ @param[in] This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Write - Switch value for Read or Write.
+ @param[in] Width - Signifies the width of the memory operations.
+ @param[in] UserAddress - The address within the PCI configuration space for the PCI controller.
+ @param[in] Count - The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[in, out] UserBuffer - For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS - The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER - Width is invalid for this PCI root bridge or Buffer is NULL.
+**/
+STATIC
+EFI_STATUS
+RootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ UINT32 InStride;
+ UINT32 OutStride;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *PciRbAddr;
+ UINT8 *PcieRegAddr;
+
+ if ((Width & 0x03) >= EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InStride = 1 << (Width & 0x03);
+ OutStride = InStride;
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
+ InStride = 0;
+ }
+
+ if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
+ OutStride = 0;
+ }
+
+ PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &UserAddress;
+ PcieRegAddr = (UINT8 *) MmPciAddress (
+ 0, /// No segment support
+ PciRbAddr->Bus,
+ PciRbAddr->Device,
+ PciRbAddr->Function,
+ 0 /// Register is added next
+ );
+
+ ///
+ /// Add the register offset to the address
+ ///
+ if (PciRbAddr->ExtendedRegister != 0) {
+ PcieRegAddr += PciRbAddr->ExtendedRegister;
+ } else {
+ PcieRegAddr += PciRbAddr->Register;
+ }
+
+ while (Count) {
+ if (Write) {
+ This->Mem.Write (This, Width, (UINTN) PcieRegAddr, 1, UserBuffer);
+ } else {
+ This->Mem.Read (This, Width, (UINTN) PcieRegAddr, 1, UserBuffer);
+ }
+
+ UserBuffer = ((UINT8 *) UserBuffer) + OutStride;
+ PcieRegAddr += InStride;
+ Count -= 1;
+ }
+
+ return EFI_SUCCESS;
+}