public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with
@ 2021-06-16 23:04 manickavasakam karpagavinayagam
  2021-06-17  2:56 ` 回复: [edk2-devel] " gaoliming
  0 siblings, 1 reply; 7+ messages in thread
From: manickavasakam karpagavinayagam @ 2021-06-16 23:04 UTC (permalink / raw)
  To: devel

[-- Attachment #1: Type: text/plain, Size: 12156 bytes --]

Add BoardTiogaPass packages to support TiogaPass Platform Enabled Network, ISCSI,IPMI, SMBIOS, Performance Measurement
Remove AST2500 UEFI option ROM driver from PurleyOpenBoardPkg

AST2500 UEFI option ROM move to edk2-non-osi ASpeedGopBinPkg Update copyright headers

manickavasakam karpagavinayagam (2):

PurleyOpenBoardPkg : Support for TiogaPass Platform

PurleyOpenBoardPkg : Override generic PciBus Driver with Platform

specific instance of PciBus driver.

.../IpmiFeaturePkg/GenericIpmi/Dxe/IpmiInit.c | 8 +-

.../Acpi/BoardAcpiDxe/AmlOffsetTable.c | 453 +-

.../Acpi/BoardAcpiDxe/BoardAcpiDxeDsdt.c | 3 +

.../BoardTiogaPass/CoreDxeInclude.dsc | 168 +

.../BoardTiogaPass/CoreUefiBootInclude.fdf | 82 +

.../BoardTiogaPass/GitEdk2MinTiogaPass.bat | 93 +

.../BasePlatformHookLib/BasePlatformHookLib.c | 389 +

.../BasePlatformHookLib.inf | 36 +

.../BoardAcpiLib/DxeBoardAcpiTableLib.c | 36 +

.../BoardAcpiLib/DxeBoardAcpiTableLib.inf | 40 +

.../BoardAcpiLib/DxeTiogaPassAcpiTableLib.c | 53 +

.../BoardAcpiLib/SmmBoardAcpiEnableLib.c | 62 +

.../BoardAcpiLib/SmmBoardAcpiEnableLib.inf | 41 +

.../BoardAcpiLib/SmmSiliconAcpiEnableLib.c | 120 +

.../BoardAcpiLib/SmmTiogaPassAcpiEnableLib.c | 37 +

.../Library/BoardInitLib/AllLanesEparam.c | 44 +

.../Library/BoardInitLib/GpioTable.c | 296 +

.../Library/BoardInitLib/IioBifur.c | 70 +

.../BoardInitLib/PeiBoardInitPostMemLib.c | 46 +

.../BoardInitLib/PeiBoardInitPostMemLib.inf | 37 +

.../BoardInitLib/PeiBoardInitPreMemLib.c | 112 +

.../BoardInitLib/PeiBoardInitPreMemLib.inf | 69 +

.../Library/BoardInitLib/PeiTiogaPassDetect.c | 28 +

.../BoardInitLib/PeiTiogaPassInitLib.h | 18 +

.../BoardInitLib/PeiTiogaPassInitPostMemLib.c | 86 +

.../BoardInitLib/PeiTiogaPassInitPreMemLib.c | 638 ++

.../Library/BoardInitLib/UsbOC.c | 46 +

.../Library/PeiReportFvLib/PeiReportFvLib.c | 138 +

.../Library/PeiReportFvLib/PeiReportFvLib.inf | 51 +

.../BoardTiogaPass/OpenBoardPkg.dsc | 245 +

.../BoardTiogaPass/OpenBoardPkg.fdf | 600 ++

.../BoardTiogaPass/PlatformPkgBuildOption.dsc | 84 +

.../BoardTiogaPass/PlatformPkgConfig.dsc | 58 +

.../BoardTiogaPass/PlatformPkgPcd.dsc | 392 ++

.../BoardTiogaPass/StructureConfig.dsc | 6236 +++++++++++++++++

.../BoardTiogaPass/__init__.py | 0

.../PurleyOpenBoardPkg/BoardTiogaPass/bld.bat | 139 +

.../BoardTiogaPass/build_board.py | 195 +

.../BoardTiogaPass/build_config.cfg | 34 +

.../BoardTiogaPass/logo.txt | 10 +

.../BoardTiogaPass/postbuild.bat | 96 +

.../BoardTiogaPass/prebuild.bat | 213 +

.../Ipmi/Library/IpmiLibKcs/IpmiLibKcs.inf | 10 +-

.../IpmiPlatformHookLib.inf | 6 +-

.../Include/Guid/PchRcVariable.h | 6 +

.../Include/Guid/SetupVariable.h | 15 +-

.../Intel/PurleyOpenBoardPkg/OpenBoardPkg.dec | 1 +

.../Bus/Pci/PciBusDxe/ComponentName.c | 170 +

.../Bus/Pci/PciBusDxe/ComponentName.h | 146 +

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c | 460 ++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 396 ++

.../Bus/Pci/PciBusDxe/PciBusDxe.inf | 112 +

.../Bus/Pci/PciBusDxe/PciBusDxe.uni | 16 +

.../Bus/Pci/PciBusDxe/PciBusDxeExtra.uni | 14 +

.../Bus/Pci/PciBusDxe/PciCommand.c | 267 +

.../Bus/Pci/PciBusDxe/PciCommand.h | 232 +

.../Bus/Pci/PciBusDxe/PciDeviceSupport.c | 1056 +++

.../Bus/Pci/PciBusDxe/PciDeviceSupport.h | 266 +

.../Bus/Pci/PciBusDxe/PciDriverOverride.c | 188 +

.../Bus/Pci/PciBusDxe/PciDriverOverride.h | 83 +

.../Bus/Pci/PciBusDxe/PciEnumerator.c | 2210 ++++++

.../Bus/Pci/PciBusDxe/PciEnumerator.h | 515 ++

.../Bus/Pci/PciBusDxe/PciEnumeratorSupport.c | 2885 ++++++++.../Bus/Pci/PciBusDxe/PciEnumeratorSupport.h | 480 ++

.../Bus/Pci/PciBusDxe/PciHotPlugSupport.c | 484 ++

.../Bus/Pci/PciBusDxe/PciHotPlugSupport.h | 205 +

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c | 2087 ++++++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h | 660 ++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c | 1809 +++++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h | 179 +

.../Bus/Pci/PciBusDxe/PciOptionRomSupport.c | 776 ++

.../Bus/Pci/PciBusDxe/PciOptionRomSupport.h | 136 +

.../Bus/Pci/PciBusDxe/PciPowerManagement.c | 82 +

.../Bus/Pci/PciBusDxe/PciPowerManagement.h | 28 +

.../Bus/Pci/PciBusDxe/PciResourceSupport.c | 2292 ++++++

.../Bus/Pci/PciBusDxe/PciResourceSupport.h | 456 ++

.../Bus/Pci/PciBusDxe/PciRomTable.c | 135 +

.../Bus/Pci/PciBusDxe/PciRomTable.h | 48 +

Platform/Intel/build.cfg | 2 +

Platform/Intel/build_bios.py | 3 +-

80 files changed, 30278 insertions(+), 240 deletions(-) create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreDxeInclude.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootInclude.fdf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/GitEdk2MinTiogaPass.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BasePlatformHookLib/BasePlatformHookLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BasePlatformHookLib/BasePlatformHookLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeBoardAcpiTableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeBoardAcpiTableLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeTiogaPassAcpiTableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmBoardAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmBoardAcpiEnableLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmSiliconAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmTiogaPassAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/AllLanesEparam.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/GpioTable.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/IioBifur.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPostMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPostMemLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPreMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPreMemLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassDetect.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitLib.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitPostMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitPreMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/UsbOC.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/PeiReportFvLib/PeiReportFvLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/PeiReportFvLib/PeiReportFvLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/OpenBoardPkg.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/OpenBoardPkg.fdf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgBuildOption.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgConfig.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgPcd.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/StructureConfig.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/__init__.py

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/bld.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/build_board.py

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/build_config.cfg

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/logo.txt

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/postbuild.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/prebuild.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.uni

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxeExtra.uni

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.h

[-- Attachment #2: Type: text/html, Size: 32923 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with
  2021-06-16 23:04 [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with manickavasakam karpagavinayagam
@ 2021-06-17  2:56 ` gaoliming
  2021-06-17 14:55   ` [EXTERNAL] " manickavasakam karpagavinayagam
  0 siblings, 1 reply; 7+ messages in thread
From: gaoliming @ 2021-06-17  2:56 UTC (permalink / raw)
  To: devel, manickavasakamk

[-- Attachment #1: Type: text/plain, Size: 13437 bytes --]

 

Please follow https://github.com/tianocore/tianocore.github.io/wiki/Commit-Message-Format to update the commit message format.

 

And, for the override PciBus module, can you give more detail why need to override PciBus? Is it possible to update Edk2 MdeModulePkg PciBus to meet the platform requirement?

 

Thanks

Liming

发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 manickavasakam karpagavinayagam
发送时间: 2021年6月17日 7:05
收件人: devel@edk2.groups.io
主题: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with

 

Add BoardTiogaPass packages to support TiogaPass Platform Enabled Network, ISCSI,IPMI, SMBIOS, Performance Measurement 
Remove AST2500 UEFI option ROM driver from PurleyOpenBoardPkg

AST2500 UEFI option ROM move to edk2-non-osi ASpeedGopBinPkg Update copyright headers

 

manickavasakam karpagavinayagam (2):

  PurleyOpenBoardPkg : Support for TiogaPass Platform

  PurleyOpenBoardPkg : Override generic PciBus Driver with Platform

    specific instance of PciBus driver.

 

.../IpmiFeaturePkg/GenericIpmi/Dxe/IpmiInit.c |    8 +-

.../Acpi/BoardAcpiDxe/AmlOffsetTable.c        |  453 +-

.../Acpi/BoardAcpiDxe/BoardAcpiDxeDsdt.c      |    3 +

.../BoardTiogaPass/CoreDxeInclude.dsc         |  168 +

.../BoardTiogaPass/CoreUefiBootInclude.fdf    |   82 +

.../BoardTiogaPass/GitEdk2MinTiogaPass.bat    |   93 +

.../BasePlatformHookLib/BasePlatformHookLib.c |  389 +

.../BasePlatformHookLib.inf                   |   36 +

.../BoardAcpiLib/DxeBoardAcpiTableLib.c       |   36 +

.../BoardAcpiLib/DxeBoardAcpiTableLib.inf     |   40 +

.../BoardAcpiLib/DxeTiogaPassAcpiTableLib.c   |   53 +

.../BoardAcpiLib/SmmBoardAcpiEnableLib.c      |   62 +

.../BoardAcpiLib/SmmBoardAcpiEnableLib.inf    |   41 +

.../BoardAcpiLib/SmmSiliconAcpiEnableLib.c    |  120 +

.../BoardAcpiLib/SmmTiogaPassAcpiEnableLib.c  |   37 +

.../Library/BoardInitLib/AllLanesEparam.c     |   44 +

.../Library/BoardInitLib/GpioTable.c          |  296 +

.../Library/BoardInitLib/IioBifur.c           |   70 +

.../BoardInitLib/PeiBoardInitPostMemLib.c     |   46 +

.../BoardInitLib/PeiBoardInitPostMemLib.inf   |   37 +

.../BoardInitLib/PeiBoardInitPreMemLib.c      |  112 +

.../BoardInitLib/PeiBoardInitPreMemLib.inf    |   69 +

.../Library/BoardInitLib/PeiTiogaPassDetect.c |   28 +

.../BoardInitLib/PeiTiogaPassInitLib.h        |   18 +

.../BoardInitLib/PeiTiogaPassInitPostMemLib.c |   86 +

.../BoardInitLib/PeiTiogaPassInitPreMemLib.c  |  638 ++

.../Library/BoardInitLib/UsbOC.c              |   46 +

.../Library/PeiReportFvLib/PeiReportFvLib.c   |  138 +

.../Library/PeiReportFvLib/PeiReportFvLib.inf |   51 +

.../BoardTiogaPass/OpenBoardPkg.dsc           |  245 +

.../BoardTiogaPass/OpenBoardPkg.fdf           |  600 ++

.../BoardTiogaPass/PlatformPkgBuildOption.dsc |   84 +

.../BoardTiogaPass/PlatformPkgConfig.dsc      |   58 +

.../BoardTiogaPass/PlatformPkgPcd.dsc         |  392 ++

.../BoardTiogaPass/StructureConfig.dsc        | 6236 +++++++++++++++++

.../BoardTiogaPass/__init__.py                |    0

.../PurleyOpenBoardPkg/BoardTiogaPass/bld.bat |  139 +

.../BoardTiogaPass/build_board.py             |  195 +

.../BoardTiogaPass/build_config.cfg           |   34 +

.../BoardTiogaPass/logo.txt                   |   10 +

.../BoardTiogaPass/postbuild.bat              |   96 +

.../BoardTiogaPass/prebuild.bat               |  213 +

.../Ipmi/Library/IpmiLibKcs/IpmiLibKcs.inf    |   10 +-

.../IpmiPlatformHookLib.inf                   |    6 +-

.../Include/Guid/PchRcVariable.h              |    6 +

.../Include/Guid/SetupVariable.h              |   15 +-

.../Intel/PurleyOpenBoardPkg/OpenBoardPkg.dec |    1 +

.../Bus/Pci/PciBusDxe/ComponentName.c         |  170 +

.../Bus/Pci/PciBusDxe/ComponentName.h         |  146 +

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c   |  460 ++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h   |  396 ++

.../Bus/Pci/PciBusDxe/PciBusDxe.inf           |  112 +

.../Bus/Pci/PciBusDxe/PciBusDxe.uni           |   16 +

.../Bus/Pci/PciBusDxe/PciBusDxeExtra.uni      |   14 +

.../Bus/Pci/PciBusDxe/PciCommand.c            |  267 +

.../Bus/Pci/PciBusDxe/PciCommand.h            |  232 +

.../Bus/Pci/PciBusDxe/PciDeviceSupport.c      | 1056 +++

.../Bus/Pci/PciBusDxe/PciDeviceSupport.h      |  266 +

.../Bus/Pci/PciBusDxe/PciDriverOverride.c     |  188 +

.../Bus/Pci/PciBusDxe/PciDriverOverride.h     |   83 +

.../Bus/Pci/PciBusDxe/PciEnumerator.c         | 2210 ++++++

.../Bus/Pci/PciBusDxe/PciEnumerator.h         |  515 ++

.../Bus/Pci/PciBusDxe/PciEnumeratorSupport.c  | 2885 ++++++++  .../Bus/Pci/PciBusDxe/PciEnumeratorSupport.h  |  480 ++

.../Bus/Pci/PciBusDxe/PciHotPlugSupport.c     |  484 ++

.../Bus/Pci/PciBusDxe/PciHotPlugSupport.h     |  205 +

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c    | 2087 ++++++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h    |  660 ++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c   | 1809 +++++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h   |  179 +

.../Bus/Pci/PciBusDxe/PciOptionRomSupport.c   |  776 ++

.../Bus/Pci/PciBusDxe/PciOptionRomSupport.h   |  136 +

.../Bus/Pci/PciBusDxe/PciPowerManagement.c    |   82 +

.../Bus/Pci/PciBusDxe/PciPowerManagement.h    |   28 +

.../Bus/Pci/PciBusDxe/PciResourceSupport.c    | 2292 ++++++

.../Bus/Pci/PciBusDxe/PciResourceSupport.h    |  456 ++

.../Bus/Pci/PciBusDxe/PciRomTable.c           |  135 +

.../Bus/Pci/PciBusDxe/PciRomTable.h           |   48 +

Platform/Intel/build.cfg                      |    2 +

Platform/Intel/build_bios.py                  |    3 +-

80 files changed, 30278 insertions(+), 240 deletions(-)  create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreDxeInclude.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootInclude.fdf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/GitEdk2MinTiogaPass.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BasePlatformHookLib/BasePlatformHookLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BasePlatformHookLib/BasePlatformHookLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeBoardAcpiTableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeBoardAcpiTableLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeTiogaPassAcpiTableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmBoardAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmBoardAcpiEnableLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmSiliconAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmTiogaPassAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/AllLanesEparam.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/GpioTable.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/IioBifur.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPostMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPostMemLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPreMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPreMemLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassDetect.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitLib.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitPostMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitPreMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/UsbOC.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/PeiReportFvLib/PeiReportFvLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/PeiReportFvLib/PeiReportFvLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/OpenBoardPkg.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/OpenBoardPkg.fdf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgBuildOption.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgConfig.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgPcd.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/StructureConfig.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/__init__.py

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/bld.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/build_board.py

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/build_config.cfg

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/logo.txt

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/postbuild.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/prebuild.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.uni

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxeExtra.uni

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.h




[-- Attachment #2: Type: text/html, Size: 29566 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with
  2021-06-17  2:56 ` 回复: [edk2-devel] " gaoliming
@ 2021-06-17 14:55   ` manickavasakam karpagavinayagam
  2021-06-17 15:19     ` Michael D Kinney
  0 siblings, 1 reply; 7+ messages in thread
From: manickavasakam karpagavinayagam @ 2021-06-17 14:55 UTC (permalink / raw)
  To: gaoliming, devel@edk2.groups.io; +Cc: Harikrishna Doppalapudi


[-- Attachment #1.1: Type: text/plain, Size: 15292 bytes --]

Liming :

Below email is the cover letter and this patch series has two changes. Sure next time, will add more comments in the cover letter also.
Please refer the attached email and it has information about the PCIBUS override changes. PCIBUS override is done based on the platform sighting and it can’t be generic.

Thank you

-Manic

From: gaoliming <gaoliming@byosoft.com.cn>
Sent: Wednesday, June 16, 2021 10:56 PM
To: devel@edk2.groups.io; Manickavasakam Karpagavinayagam <manickavasakamk@ami.com>
Subject: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with


**CAUTION: The e-mail below is from an external source. Please exercise caution before opening attachments, clicking links, or following guidance.**

Please follow https://github.com/tianocore/tianocore.github.io/wiki/Commit-Message-Format<https://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FCommit-Message-Format&data=04%7C01%7Cmanickavasakamk%40ami.com%7C478d38ff236a496b1f8a08d9313b78b5%7C27e97857e15f486cb58e86c2b3040f93%7C1%7C0%7C637594953779151841%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=RhP%2BBy62unxjQauvze06TjzReq%2FJfUgq7%2B9DR0R8kNY%3D&reserved=0> to update the commit message format.

And, for the override PciBus module, can you give more detail why need to override PciBus? Is it possible to update Edk2 MdeModulePkg PciBus to meet the platform requirement?

Thanks
Liming
发件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> 代表 manickavasakam karpagavinayagam
发送时间: 2021年6月17日 7:05
收件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
主题: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with


Add BoardTiogaPass packages to support TiogaPass Platform Enabled Network, ISCSI,IPMI, SMBIOS, Performance Measurement
Remove AST2500 UEFI option ROM driver from PurleyOpenBoardPkg

AST2500 UEFI option ROM move to edk2-non-osi ASpeedGopBinPkg Update copyright headers



manickavasakam karpagavinayagam (2):

  PurleyOpenBoardPkg : Support for TiogaPass Platform

  PurleyOpenBoardPkg : Override generic PciBus Driver with Platform

    specific instance of PciBus driver.



.../IpmiFeaturePkg/GenericIpmi/Dxe/IpmiInit.c |    8 +-

.../Acpi/BoardAcpiDxe/AmlOffsetTable.c        |  453 +-

.../Acpi/BoardAcpiDxe/BoardAcpiDxeDsdt.c      |    3 +

.../BoardTiogaPass/CoreDxeInclude.dsc         |  168 +

.../BoardTiogaPass/CoreUefiBootInclude.fdf    |   82 +

.../BoardTiogaPass/GitEdk2MinTiogaPass.bat    |   93 +

.../BasePlatformHookLib/BasePlatformHookLib.c |  389 +

.../BasePlatformHookLib.inf                   |   36 +

.../BoardAcpiLib/DxeBoardAcpiTableLib.c       |   36 +

.../BoardAcpiLib/DxeBoardAcpiTableLib.inf     |   40 +

.../BoardAcpiLib/DxeTiogaPassAcpiTableLib.c   |   53 +

.../BoardAcpiLib/SmmBoardAcpiEnableLib.c      |   62 +

.../BoardAcpiLib/SmmBoardAcpiEnableLib.inf    |   41 +

.../BoardAcpiLib/SmmSiliconAcpiEnableLib.c    |  120 +

.../BoardAcpiLib/SmmTiogaPassAcpiEnableLib.c  |   37 +

.../Library/BoardInitLib/AllLanesEparam.c     |   44 +

.../Library/BoardInitLib/GpioTable.c          |  296 +

.../Library/BoardInitLib/IioBifur.c           |   70 +

.../BoardInitLib/PeiBoardInitPostMemLib.c     |   46 +

.../BoardInitLib/PeiBoardInitPostMemLib.inf   |   37 +

.../BoardInitLib/PeiBoardInitPreMemLib.c      |  112 +

.../BoardInitLib/PeiBoardInitPreMemLib.inf    |   69 +

.../Library/BoardInitLib/PeiTiogaPassDetect.c |   28 +

.../BoardInitLib/PeiTiogaPassInitLib.h        |   18 +

.../BoardInitLib/PeiTiogaPassInitPostMemLib.c |   86 +

.../BoardInitLib/PeiTiogaPassInitPreMemLib.c  |  638 ++

.../Library/BoardInitLib/UsbOC.c              |   46 +

.../Library/PeiReportFvLib/PeiReportFvLib.c   |  138 +

.../Library/PeiReportFvLib/PeiReportFvLib.inf |   51 +

.../BoardTiogaPass/OpenBoardPkg.dsc           |  245 +

.../BoardTiogaPass/OpenBoardPkg.fdf           |  600 ++

.../BoardTiogaPass/PlatformPkgBuildOption.dsc |   84 +

.../BoardTiogaPass/PlatformPkgConfig.dsc      |   58 +

.../BoardTiogaPass/PlatformPkgPcd.dsc         |  392 ++

.../BoardTiogaPass/StructureConfig.dsc        | 6236 +++++++++++++++++

.../BoardTiogaPass/__init__.py                |    0

.../PurleyOpenBoardPkg/BoardTiogaPass/bld.bat |  139 +

.../BoardTiogaPass/build_board.py             |  195 +

.../BoardTiogaPass/build_config.cfg           |   34 +

.../BoardTiogaPass/logo.txt                   |   10 +

.../BoardTiogaPass/postbuild.bat              |   96 +

.../BoardTiogaPass/prebuild.bat               |  213 +

.../Ipmi/Library/IpmiLibKcs/IpmiLibKcs.inf    |   10 +-

.../IpmiPlatformHookLib.inf                   |    6 +-

.../Include/Guid/PchRcVariable.h              |    6 +

.../Include/Guid/SetupVariable.h              |   15 +-

.../Intel/PurleyOpenBoardPkg/OpenBoardPkg.dec |    1 +

.../Bus/Pci/PciBusDxe/ComponentName.c         |  170 +

.../Bus/Pci/PciBusDxe/ComponentName.h         |  146 +

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c   |  460 ++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h   |  396 ++

.../Bus/Pci/PciBusDxe/PciBusDxe.inf           |  112 +

.../Bus/Pci/PciBusDxe/PciBusDxe.uni           |   16 +

.../Bus/Pci/PciBusDxe/PciBusDxeExtra.uni      |   14 +

.../Bus/Pci/PciBusDxe/PciCommand.c            |  267 +

.../Bus/Pci/PciBusDxe/PciCommand.h            |  232 +

.../Bus/Pci/PciBusDxe/PciDeviceSupport.c      | 1056 +++

.../Bus/Pci/PciBusDxe/PciDeviceSupport.h      |  266 +

.../Bus/Pci/PciBusDxe/PciDriverOverride.c     |  188 +

.../Bus/Pci/PciBusDxe/PciDriverOverride.h     |   83 +

.../Bus/Pci/PciBusDxe/PciEnumerator.c         | 2210 ++++++

.../Bus/Pci/PciBusDxe/PciEnumerator.h         |  515 ++

.../Bus/Pci/PciBusDxe/PciEnumeratorSupport.c  | 2885 ++++++++  .../Bus/Pci/PciBusDxe/PciEnumeratorSupport.h  |  480 ++

.../Bus/Pci/PciBusDxe/PciHotPlugSupport.c     |  484 ++

.../Bus/Pci/PciBusDxe/PciHotPlugSupport.h     |  205 +

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c    | 2087 ++++++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h    |  660 ++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c   | 1809 +++++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h   |  179 +

.../Bus/Pci/PciBusDxe/PciOptionRomSupport.c   |  776 ++

.../Bus/Pci/PciBusDxe/PciOptionRomSupport.h   |  136 +

.../Bus/Pci/PciBusDxe/PciPowerManagement.c    |   82 +

.../Bus/Pci/PciBusDxe/PciPowerManagement.h    |   28 +

.../Bus/Pci/PciBusDxe/PciResourceSupport.c    | 2292 ++++++

.../Bus/Pci/PciBusDxe/PciResourceSupport.h    |  456 ++

.../Bus/Pci/PciBusDxe/PciRomTable.c           |  135 +

.../Bus/Pci/PciBusDxe/PciRomTable.h           |   48 +

Platform/Intel/build.cfg                      |    2 +

Platform/Intel/build_bios.py                  |    3 +-

80 files changed, 30278 insertions(+), 240 deletions(-)  create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreDxeInclude.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootInclude.fdf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/GitEdk2MinTiogaPass.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BasePlatformHookLib/BasePlatformHookLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BasePlatformHookLib/BasePlatformHookLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeBoardAcpiTableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeBoardAcpiTableLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeTiogaPassAcpiTableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmBoardAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmBoardAcpiEnableLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmSiliconAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmTiogaPassAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/AllLanesEparam.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/GpioTable.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/IioBifur.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPostMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPostMemLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPreMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPreMemLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassDetect.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitLib.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitPostMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitPreMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/UsbOC.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/PeiReportFvLib/PeiReportFvLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/PeiReportFvLib/PeiReportFvLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/OpenBoardPkg.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/OpenBoardPkg.fdf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgBuildOption.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgConfig.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgPcd.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/StructureConfig.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/__init__.py

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/bld.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/build_board.py

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/build_config.cfg

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/logo.txt

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/postbuild.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/prebuild.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.uni

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxeExtra.uni

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.h

-The information contained in this message may be confidential and proprietary to American Megatrends (AMI). This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited. Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.

[-- Attachment #1.2: Type: text/html, Size: 30513 bytes --]

[-- Attachment #2: Type: message/rfc822, Size: 617235 bytes --]

From: Nate DeSimone <nathaniel.l.desimone@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: Manickavasakam Karpagavinayagam <manickavasakamk@ami.com>, Isaac Oram <isaac.w.oram@intel.com>, Felix Polyudov <Felixp@ami.com>, Harikrishna Doppalapudi <Harikrishnad@ami.com>, Manish Jha <manishj@ami.com>, Zachary Bobroff <zacharyb@ami.com>
Subject: [EXTERNAL] [edk2-platforms] [PATCH V1 2/2] PurleyOpenBoardPkg : Override generic PciBus Driver with Platform specific instance of PciBus driver.
Date: Thu, 17 Jun 2021 00:51:37 +0000
Message-ID: <20210617005137.2583-6-nathaniel.l.desimone@intel.com>


**CAUTION: The e-mail below is from an external source. Please exercise caution before opening attachments, clicking links, or following guidance.**

From: manickavasakam karpagavinayagam <manickavasakamk@ami.com>

Overriden generic PciBus Driver with Platform specific instance of PciBus driver
To skip SPI controller initialization during PCI enumeration to avoid SET variable
assert issue during POST
To skip executing a specific MLX card UEFI OPROM
Move PurleyOpenBoardPkg/Override/edk2/MdeModulePkg/Bus/Pci/PciBusDxe to
PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe

Cc: Isaac Oram <isaac.w.oram@intel.com>
Cc: Felix Polyudov <Felixp@ami.com>
Cc: Harikrishna Doppalapudi <harikrishnad@ami.com>
Cc: Manish Jha <manishj@ami.com>
Cc: Zachary Bobroff <zacharyb@ami.com>
Cc: Manickavasakam Karpagavinayagam <manickavasakamk@ami.com>
---
 .../BoardTiogaPass/CoreDxeInclude.dsc         |    5 +-
 .../BoardTiogaPass/CoreUefiBootInclude.fdf    |    5 +-
 .../Bus/Pci/PciBusDxe/ComponentName.c         |  170 +
 .../Bus/Pci/PciBusDxe/ComponentName.h         |  146 +
 .../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c   |  460 +++
 .../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h   |  396 +++
 .../Bus/Pci/PciBusDxe/PciBusDxe.inf           |  112 +
 .../Bus/Pci/PciBusDxe/PciBusDxe.uni           |   16 +
 .../Bus/Pci/PciBusDxe/PciBusDxeExtra.uni      |   14 +
 .../Bus/Pci/PciBusDxe/PciCommand.c            |  267 ++
 .../Bus/Pci/PciBusDxe/PciCommand.h            |  232 ++
 .../Bus/Pci/PciBusDxe/PciDeviceSupport.c      | 1056 ++++++
 .../Bus/Pci/PciBusDxe/PciDeviceSupport.h      |  266 ++
 .../Bus/Pci/PciBusDxe/PciDriverOverride.c     |  188 ++
 .../Bus/Pci/PciBusDxe/PciDriverOverride.h     |   83 +
 .../Bus/Pci/PciBusDxe/PciEnumerator.c         | 2210 +++++++++++++
 .../Bus/Pci/PciBusDxe/PciEnumerator.h         |  515 +++
 .../Bus/Pci/PciBusDxe/PciEnumeratorSupport.c  | 2885 +++++++++++++++++
 .../Bus/Pci/PciBusDxe/PciEnumeratorSupport.h  |  480 +++
 .../Bus/Pci/PciBusDxe/PciHotPlugSupport.c     |  484 +++
 .../Bus/Pci/PciBusDxe/PciHotPlugSupport.h     |  205 ++
 .../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c    | 2087 ++++++++++++
 .../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h    |  660 ++++
 .../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c   | 1809 +++++++++++
 .../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h   |  179 +
 .../Bus/Pci/PciBusDxe/PciOptionRomSupport.c   |  776 +++++
 .../Bus/Pci/PciBusDxe/PciOptionRomSupport.h   |  136 +
 .../Bus/Pci/PciBusDxe/PciPowerManagement.c    |   82 +
 .../Bus/Pci/PciBusDxe/PciPowerManagement.h    |   28 +
 .../Bus/Pci/PciBusDxe/PciResourceSupport.c    | 2292 +++++++++++++
 .../Bus/Pci/PciBusDxe/PciResourceSupport.h    |  456 +++
 .../Bus/Pci/PciBusDxe/PciRomTable.c           |  135 +
 .../Bus/Pci/PciBusDxe/PciRomTable.h           |   48 +
 33 files changed, 18881 insertions(+), 2 deletions(-)
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.uni
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxeExtra.uni
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.c
 create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.h

diff --git a/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreDxeInclude.dsc b/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreDxeInclude.dsc
index 7dcb892dd5..b0660d72dd 100644
--- a/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreDxeInclude.dsc
+++ b/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreDxeInclude.dsc
@@ -78,7 +78,10 @@
   PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf

   #MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
-  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+#TiogaPass Override START :Skip  OPROM for specific Mellanox card & SPI Controller
+  #MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+  $(PLATFORM_BOARD_PACKAGE)/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+#TiogaPass Override END

   MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf
   MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
diff --git a/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootInclude.fdf b/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootInclude.fdf
index 478a818546..141ce5dda3 100644
--- a/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootInclude.fdf
+++ b/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootInclude.fdf
@@ -42,7 +42,10 @@ INF  MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
 INF  PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf

 #INF  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
-INF  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+#TiogaPass Override START :Skip OPROM for specific Mellanox card & SPI Controller
+ #INF  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+ INF  $(PLATFORM_BOARD_PACKAGE)/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+#TiogaPass Override END

 INF  MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf
 INF  MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.c
new file mode 100644
index 0000000000..f3554507e2
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.c
@@ -0,0 +1,170 @@
+/** @file
+  EFI Component Name functions implementation for PCI Bus module.
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gPciBusComponentName = {
+  PciBusComponentNameGetDriverName,
+  PciBusComponentNameGetControllerName,
+  "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPciBusComponentName2 = {
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) PciBusComponentNameGetDriverName,
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) PciBusComponentNameGetControllerName,
+  "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mPciBusDriverNameTable[] = {
+  { "eng;en", (CHAR16 *) L"PCI Bus Driver" },
+  { NULL , NULL }
+};
+
+/**
+  Retrieves a Unicode string that is the user readable name of the driver.
+
+  This function retrieves the user readable name of a driver in the form of a
+  Unicode string. If the driver specified by This has a user readable name in
+  the language specified by Language, then a pointer to the driver name is
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+  by This does not support the language specified by Language,
+  then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language. This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified
+                                in RFC 4646 or ISO 639-2 language code format.
+
+  @param  DriverName[out]       A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                driver specified by This in the language
+                                specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
+                                This and the language specified by Language was
+                                returned in DriverName.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+PciBusComponentNameGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mPciBusDriverNameTable,
+           DriverName,
+           (BOOLEAN)(This == &gPciBusComponentName)
+           );
+}
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable name of the controller specified by
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the
+  driver specified by This has a user readable name in the language specified by
+  Language, then a pointer to the controller name is returned in ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
+  managing the controller specified by ControllerHandle and ChildHandle,
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  ControllerHandle[in]  The handle of a controller that the driver
+                                specified by This is managing.  This handle
+                                specifies the controller whose name is to be
+                                returned.
+
+  @param  ChildHandle[in]       The handle of the child controller to retrieve
+                                the name of.  This is an optional parameter that
+                                may be NULL.  It will be NULL for device
+                                drivers.  It will also be NULL for a bus drivers
+                                that wish to retrieve the name of the bus
+                                controller.  It will not be NULL for a bus
+                                driver that wishes to retrieve the name of a
+                                child controller.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language.  This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified in
+                                RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                controller specified by ControllerHandle and
+                                ChildHandle in the language specified by
+                                Language from the point of view of the driver
+                                specified by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in
+                                the language specified by Language for the
+                                driver specified by This was returned in
+                                DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+                                EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
+                                managing the controller specified by
+                                ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+PciBusComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
+  IN  EFI_HANDLE                                      ControllerHandle,
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,
+  IN  CHAR8                                           *Language,
+  OUT CHAR16                                          **ControllerName
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.h
new file mode 100644
index 0000000000..fc3c672760
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.h
@@ -0,0 +1,146 @@
+/** @file
+  EFI Component Name functions declaration for PCI Bus module.
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#ifndef _EFI_PCI_BUS_COMPONENT_NAME_H_
+#define _EFI_PCI_BUS_COMPONENT_NAME_H_
+
+extern EFI_COMPONENT_NAME_PROTOCOL   gPciBusComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL  gPciBusComponentName2;
+
+//
+// EFI Component Name Functions
+//
+/**
+  Retrieves a Unicode string that is the user readable name of the driver.
+
+  This function retrieves the user readable name of a driver in the form of a
+  Unicode string. If the driver specified by This has a user readable name in
+  the language specified by Language, then a pointer to the driver name is
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+  by This does not support the language specified by Language,
+  then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language. This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified
+                                in RFC 4646 or ISO 639-2 language code format.
+
+  @param  DriverName[out]       A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                driver specified by This in the language
+                                specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
+                                This and the language specified by Language was
+                                returned in DriverName.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+PciBusComponentNameGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  );
+
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable name of the controller specified by
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the
+  driver specified by This has a user readable name in the language specified by
+  Language, then a pointer to the controller name is returned in ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
+  managing the controller specified by ControllerHandle and ChildHandle,
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  ControllerHandle[in]  The handle of a controller that the driver
+                                specified by This is managing.  This handle
+                                specifies the controller whose name is to be
+                                returned.
+
+  @param  ChildHandle[in]       The handle of the child controller to retrieve
+                                the name of.  This is an optional parameter that
+                                may be NULL.  It will be NULL for device
+                                drivers.  It will also be NULL for a bus drivers
+                                that wish to retrieve the name of the bus
+                                controller.  It will not be NULL for a bus
+                                driver that wishes to retrieve the name of a
+                                child controller.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language.  This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified in
+                                RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                controller specified by ControllerHandle and
+                                ChildHandle in the language specified by
+                                Language from the point of view of the driver
+                                specified by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in
+                                the language specified by Language for the
+                                driver specified by This was returned in
+                                DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+                                EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
+                                managing the controller specified by
+                                ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+PciBusComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
+  IN  EFI_HANDLE                                      ControllerHandle,
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,
+  IN  CHAR8                                           *Language,
+  OUT CHAR16                                          **ControllerName
+  );
+
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
new file mode 100644
index 0000000000..682b2dac38
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
@@ -0,0 +1,460 @@
+/** @file
+  Driver Binding functions for PCI Bus module.
+
+  Single PCI bus driver instance will manager all PCI Root Bridges in one EFI based firmware,
+  since all PCI Root Bridges' resources need to be managed together.
+  Supported() function will try to get PCI Root Bridge IO Protocol.
+  Start() function will get PCI Host Bridge Resource Allocation Protocol to manage all
+  PCI Root Bridges. So it means platform needs install PCI Root Bridge IO protocol for each
+  PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+
+//
+// PCI Bus Driver Global Variables
+//
+EFI_DRIVER_BINDING_PROTOCOL                   gPciBusDriverBinding = {
+  PciBusDriverBindingSupported,
+  PciBusDriverBindingStart,
+  PciBusDriverBindingStop,
+  0xa,
+  NULL,
+  NULL
+};
+
+EFI_HANDLE                                    gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];
+EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL  *gIncompatiblePciDeviceSupport = NULL;
+UINTN                                         gPciHostBridgeNumber = 0;
+BOOLEAN                                       gFullEnumeration     = TRUE;
+UINT64                                        gAllOne              = 0xFFFFFFFFFFFFFFFFULL;
+UINT64                                        gAllZero             = 0;
+
+EFI_PCI_PLATFORM_PROTOCOL                     *gPciPlatformProtocol;
+EFI_PCI_OVERRIDE_PROTOCOL                     *gPciOverrideProtocol;
+EDKII_IOMMU_PROTOCOL                          *mIoMmuProtocol;
+EDKII_DEVICE_SECURITY_PROTOCOL                *mDeviceSecurityProtocol;
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL mPciHotPlugRequest = {
+  PciHotPlugRequestNotify
+};
+
+/**
+  The Entry Point for PCI Bus module. The user code starts with this function.
+
+  Installs driver module protocols and. Creates virtual device handles for ConIn,
+  ConOut, and StdErr. Installs Simple Text In protocol, Simple Text In Ex protocol,
+  Simple Pointer protocol, Absolute Pointer protocol on those virtual handlers.
+  Installs Graphics Output protocol and/or UGA Draw protocol if needed.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in] SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       The entry point is executed successfully.
+  @retval other             Some error occurred when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+PciBusEntryPoint (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  EFI_HANDLE  Handle;
+
+  //
+  // Initializes PCI devices pool
+  //
+  InitializePciDevicePool ();
+
+  //
+  // Install driver model protocol(s).
+  //
+  Status = EfiLibInstallDriverBindingComponentName2 (
+             ImageHandle,
+             SystemTable,
+             &gPciBusDriverBinding,
+             ImageHandle,
+             &gPciBusComponentName,
+             &gPciBusComponentName2
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+    //
+    // If Hot Plug is supported, install EFI PCI Hot Plug Request protocol.
+    //
+    Handle = NULL;
+    Status = gBS->InstallProtocolInterface (
+                    &Handle,
+                    &gEfiPciHotPlugRequestProtocolGuid,
+                    EFI_NATIVE_INTERFACE,
+                    &mPciHotPlugRequest
+                    );
+  }
+
+  return Status;
+}
+
+/**
+  Test to see if this driver supports ControllerHandle. Any ControllerHandle
+  than contains a gEfiPciRootBridgeIoProtocolGuid protocol can be supported.
+
+  @param  This                Protocol instance pointer.
+  @param  Controller          Handle of device to test.
+  @param  RemainingDevicePath Optional parameter use to pick a specific child
+                              device to start.
+
+  @retval EFI_SUCCESS         This driver supports this device.
+  @retval EFI_ALREADY_STARTED This driver is already running on this device.
+  @retval other               This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+  EFI_DEV_PATH_PTR                Node;
+
+  //
+  // Check RemainingDevicePath validation
+  //
+  if (RemainingDevicePath != NULL) {
+    //
+    // Check if RemainingDevicePath is the End of Device Path Node,
+    // if yes, go on checking other conditions
+    //
+    if (!IsDevicePathEnd (RemainingDevicePath)) {
+      //
+      // If RemainingDevicePath isn't the End of Device Path Node,
+      // check its validation
+      //
+      Node.DevPath = RemainingDevicePath;
+      if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||
+          Node.DevPath->SubType != HW_PCI_DP         ||
+          DevicePathNodeLength(Node.DevPath) != sizeof(PCI_DEVICE_PATH)) {
+        return EFI_UNSUPPORTED;
+      }
+    }
+  }
+
+  //
+  // Check if Pci Root Bridge IO protocol is installed by platform
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciRootBridgeIoProtocolGuid,
+                  (VOID **) &PciRootBridgeIo,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (Status == EFI_ALREADY_STARTED) {
+    return EFI_SUCCESS;
+  }
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Close the I/O Abstraction(s) used to perform the supported test
+  //
+  gBS->CloseProtocol (
+        Controller,
+        &gEfiPciRootBridgeIoProtocolGuid,
+        This->DriverBindingHandle,
+        Controller
+        );
+
+  //
+  // Open the EFI Device Path protocol needed to perform the supported test
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID **) &ParentDevicePath,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (Status == EFI_ALREADY_STARTED) {
+    return EFI_SUCCESS;
+  }
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Close protocol, don't use device path protocol in the Support() function
+  //
+  gBS->CloseProtocol (
+        Controller,
+        &gEfiDevicePathProtocolGuid,
+        This->DriverBindingHandle,
+        Controller
+        );
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Start this driver on ControllerHandle and enumerate Pci bus and start
+  all device under PCI bus.
+
+  @param  This                 Protocol instance pointer.
+  @param  Controller           Handle of device to bind driver to.
+  @param  RemainingDevicePath  Optional parameter use to pick a specific child
+                               device to start.
+
+  @retval EFI_SUCCESS          This driver is added to ControllerHandle.
+  @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.
+  @retval other                This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+  //
+  // Initialize PciRootBridgeIo to suppress incorrect compiler warning.
+  //
+  PciRootBridgeIo = NULL;
+
+  //
+  // Check RemainingDevicePath validation
+  //
+  if (RemainingDevicePath != NULL) {
+    //
+    // Check if RemainingDevicePath is the End of Device Path Node,
+    // if yes, return EFI_SUCCESS
+    //
+    if (IsDevicePathEnd (RemainingDevicePath)) {
+      return EFI_SUCCESS;
+    }
+  }
+
+  gBS->LocateProtocol (
+         &gEfiIncompatiblePciDeviceSupportProtocolGuid,
+         NULL,
+         (VOID **) &gIncompatiblePciDeviceSupport
+         );
+
+  //
+  // If PCI Platform protocol is available, get it now.
+  // If the platform implements this, it must be installed before BDS phase
+  //
+  gPciPlatformProtocol = NULL;
+  gBS->LocateProtocol (
+        &gEfiPciPlatformProtocolGuid,
+        NULL,
+        (VOID **) &gPciPlatformProtocol
+        );
+
+  //
+  // If PCI Platform protocol doesn't exist, try to Pci Override Protocol.
+  //
+  if (gPciPlatformProtocol == NULL) {
+    gPciOverrideProtocol = NULL;
+    gBS->LocateProtocol (
+          &gEfiPciOverrideProtocolGuid,
+          NULL,
+          (VOID **) &gPciOverrideProtocol
+          );
+  }
+
+  if (mIoMmuProtocol == NULL) {
+    gBS->LocateProtocol (
+          &gEdkiiIoMmuProtocolGuid,
+          NULL,
+          (VOID **) &mIoMmuProtocol
+          );
+  }
+
+  if (mDeviceSecurityProtocol == NULL) {
+    gBS->LocateProtocol (
+          &gEdkiiDeviceSecurityProtocolGuid,
+          NULL,
+          (VOID **) &mDeviceSecurityProtocol
+          );
+  }
+
+  if (PcdGetBool (PcdPciDisableBusEnumeration)) {
+    gFullEnumeration = FALSE;
+  } else {
+    gFullEnumeration = (BOOLEAN) ((SearchHostBridgeHandle (Controller) ? FALSE : TRUE));
+  }
+
+  //
+  // Open Device Path Protocol for PCI root bridge
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID **) &ParentDevicePath,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Report Status Code to indicate PCI bus starts
+  //
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+    EFI_PROGRESS_CODE,
+    (EFI_IO_BUS_PCI | EFI_IOB_PC_INIT),
+    ParentDevicePath
+    );
+
+  Status = EFI_SUCCESS;
+  //
+  // Enumerate the entire host bridge
+  // After enumeration, a database that records all the device information will be created
+  //
+  //
+  if (gFullEnumeration) {
+    //
+    // Get the rootbridge Io protocol to find the host bridge handle
+    //
+    Status = gBS->OpenProtocol (
+                    Controller,
+                    &gEfiPciRootBridgeIoProtocolGuid,
+                    (VOID **) &PciRootBridgeIo,
+                    gPciBusDriverBinding.DriverBindingHandle,
+                    Controller,
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                    );
+
+    if (!EFI_ERROR (Status)) {
+      Status = PciEnumerator (Controller, PciRootBridgeIo->ParentHandle);
+    }
+  } else {
+    //
+    // If PCI bus has already done the full enumeration, never do it again
+    //
+    Status = PciEnumeratorLight (Controller);
+  }
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Start all the devices under the entire host bridge.
+  //
+  StartPciDevices (Controller);
+
+  if (gFullEnumeration) {
+    gFullEnumeration = FALSE;
+
+    Status = gBS->InstallProtocolInterface (
+                    &PciRootBridgeIo->ParentHandle,
+                    &gEfiPciEnumerationCompleteProtocolGuid,
+                    EFI_NATIVE_INTERFACE,
+                    NULL
+                    );
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  return Status;
+}
+
+/**
+  Stop this driver on ControllerHandle. Support stopping any child handles
+  created by this driver.
+
+  @param  This              Protocol instance pointer.
+  @param  Controller        Handle of device to stop driver on.
+  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
+                            children is zero stop the entire bus driver.
+  @param  ChildHandleBuffer List of Child Handles to Stop.
+
+  @retval EFI_SUCCESS       This driver is removed ControllerHandle.
+  @retval other             This driver was not removed from this device.
+
+**/
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
+  IN  EFI_HANDLE                    Controller,
+  IN  UINTN                         NumberOfChildren,
+  IN  EFI_HANDLE                    *ChildHandleBuffer
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       Index;
+  BOOLEAN     AllChildrenStopped;
+
+  if (NumberOfChildren == 0) {
+    //
+    // Close the bus driver
+    //
+    gBS->CloseProtocol (
+          Controller,
+          &gEfiDevicePathProtocolGuid,
+          This->DriverBindingHandle,
+          Controller
+          );
+    gBS->CloseProtocol (
+          Controller,
+          &gEfiPciRootBridgeIoProtocolGuid,
+          This->DriverBindingHandle,
+          Controller
+          );
+
+    DestroyRootBridgeByHandle (
+      Controller
+      );
+
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Stop all the children
+  //
+
+  AllChildrenStopped = TRUE;
+
+  for (Index = 0; Index < NumberOfChildren; Index++) {
+
+    //
+    // De register all the pci device
+    //
+    Status = DeRegisterPciDevice (Controller, ChildHandleBuffer[Index]);
+
+    if (EFI_ERROR (Status)) {
+      AllChildrenStopped = FALSE;
+    }
+  }
+
+  if (!AllChildrenStopped) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  return EFI_SUCCESS;
+}
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
new file mode 100644
index 0000000000..967933e278
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -0,0 +1,396 @@
+/** @file
+  Header files and data structures needed by PCI Bus module.
+
+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#ifndef _EFI_PCI_BUS_H_
+#define _EFI_PCI_BUS_H_
+
+#include <PiDxe.h>
+
+#include <Protocol/LoadedImage.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/LoadFile2.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/PciHotPlugRequest.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/PciPlatform.h>
+#include <Protocol/PciHotPlugInit.h>
+#include <Protocol/Decompress.h>
+#include <Protocol/BusSpecificDriverOverride.h>
+#include <Protocol/IncompatiblePciDeviceSupport.h>
+#include <Protocol/PciOverride.h>
+#include <Protocol/PciEnumerationComplete.h>
+#include <Protocol/IoMmu.h>
+#include <Protocol/DeviceSecurity.h>
+
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/Acpi.h>
+
+typedef struct _PCI_IO_DEVICE              PCI_IO_DEVICE;
+typedef struct _PCI_BAR                    PCI_BAR;
+
+#define EFI_PCI_RID(Bus, Device, Function)  (((UINT32)Bus << 8) + ((UINT32)Device << 3) + (UINT32)Function)
+#define EFI_PCI_BUS_OF_RID(RID)             ((UINT32)RID >> 8)
+
+#define     EFI_PCI_IOV_POLICY_ARI           0x0001
+#define     EFI_PCI_IOV_POLICY_SRIOV         0x0002
+#define     EFI_PCI_IOV_POLICY_MRIOV         0x0004
+
+typedef enum {
+  PciBarTypeUnknown = 0,
+  PciBarTypeIo16,
+  PciBarTypeIo32,
+  PciBarTypeMem32,
+  PciBarTypePMem32,
+  PciBarTypeMem64,
+  PciBarTypePMem64,
+  PciBarTypeOpRom,
+  PciBarTypeIo,
+  PciBarTypeMem,
+  PciBarTypeMaxType
+} PCI_BAR_TYPE;
+
+#include "ComponentName.h"
+#include "PciIo.h"
+#include "PciCommand.h"
+#include "PciDeviceSupport.h"
+#include "PciEnumerator.h"
+#include "PciEnumeratorSupport.h"
+#include "PciDriverOverride.h"
+#include "PciRomTable.h"
+#include "PciOptionRomSupport.h"
+#include "PciPowerManagement.h"
+#include "PciHotPlugSupport.h"
+#include "PciLib.h"
+
+#define VGABASE1  0x3B0
+#define VGALIMIT1 0x3BB
+
+#define VGABASE2  0x3C0
+#define VGALIMIT2 0x3DF
+
+#define ISABASE   0x100
+#define ISALIMIT  0x3FF
+
+//
+// PCI BAR parameters
+//
+struct _PCI_BAR {
+  UINT64        BaseAddress;
+  UINT64        Length;
+  UINT64        Alignment;
+  PCI_BAR_TYPE  BarType;
+  BOOLEAN       BarTypeFixed;
+  UINT16        Offset;
+};
+
+//
+// defined in PCI Card Specification, 8.0
+//
+#define PCI_CARD_MEMORY_BASE_0                0x1C
+#define PCI_CARD_MEMORY_LIMIT_0               0x20
+#define PCI_CARD_MEMORY_BASE_1                0x24
+#define PCI_CARD_MEMORY_LIMIT_1               0x28
+#define PCI_CARD_IO_BASE_0_LOWER              0x2C
+#define PCI_CARD_IO_BASE_0_UPPER              0x2E
+#define PCI_CARD_IO_LIMIT_0_LOWER             0x30
+#define PCI_CARD_IO_LIMIT_0_UPPER             0x32
+#define PCI_CARD_IO_BASE_1_LOWER              0x34
+#define PCI_CARD_IO_BASE_1_UPPER              0x36
+#define PCI_CARD_IO_LIMIT_1_LOWER             0x38
+#define PCI_CARD_IO_LIMIT_1_UPPER             0x3A
+#define PCI_CARD_BRIDGE_CONTROL               0x3E
+
+#define PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE BIT8
+#define PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE BIT9
+
+#define RB_IO_RANGE                           1
+#define RB_MEM32_RANGE                        2
+#define RB_PMEM32_RANGE                       3
+#define RB_MEM64_RANGE                        4
+#define RB_PMEM64_RANGE                       5
+
+#define PPB_BAR_0                             0
+#define PPB_BAR_1                             1
+#define PPB_IO_RANGE                          2
+#define PPB_MEM32_RANGE                       3
+#define PPB_PMEM32_RANGE                      4
+#define PPB_PMEM64_RANGE                      5
+#define PPB_MEM64_RANGE                       0xFF
+
+#define P2C_BAR_0                             0
+#define P2C_MEM_1                             1
+#define P2C_MEM_2                             2
+#define P2C_IO_1                              3
+#define P2C_IO_2                              4
+
+#define EFI_BRIDGE_IO32_DECODE_SUPPORTED      0x0001
+#define EFI_BRIDGE_PMEM32_DECODE_SUPPORTED    0x0002
+#define EFI_BRIDGE_PMEM64_DECODE_SUPPORTED    0x0004
+#define EFI_BRIDGE_IO16_DECODE_SUPPORTED      0x0008
+#define EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED 0x0010
+#define EFI_BRIDGE_MEM64_DECODE_SUPPORTED     0x0020
+#define EFI_BRIDGE_MEM32_DECODE_SUPPORTED     0x0040
+
+#define PCI_MAX_HOST_BRIDGE_NUM               0x0010
+
+//
+// Define option for attribute
+//
+#define EFI_SET_SUPPORTS    0
+#define EFI_SET_ATTRIBUTES  1
+
+#define PCI_IO_DEVICE_SIGNATURE               SIGNATURE_32 ('p', 'c', 'i', 'o')
+
+struct _PCI_IO_DEVICE {
+  UINT32                                    Signature;
+  EFI_HANDLE                                Handle;
+  EFI_PCI_IO_PROTOCOL                       PciIo;
+  LIST_ENTRY                                Link;
+
+  EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL PciDriverOverride;
+  EFI_DEVICE_PATH_PROTOCOL                  *DevicePath;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *PciRootBridgeIo;
+  EFI_LOAD_FILE2_PROTOCOL                   LoadFile2;
+
+  //
+  // PCI configuration space header type
+  //
+  PCI_TYPE00                                Pci;
+
+  //
+  // Bus number, Device number, Function number
+  //
+  UINT8                                     BusNumber;
+  UINT8                                     DeviceNumber;
+  UINT8                                     FunctionNumber;
+
+  //
+  // BAR for this PCI Device
+  //
+  PCI_BAR                                   PciBar[PCI_MAX_BAR];
+
+  //
+  // The bridge device this pci device is subject to
+  //
+  PCI_IO_DEVICE                             *Parent;
+
+  //
+  // A linked list for children Pci Device if it is bridge device
+  //
+  LIST_ENTRY                                ChildList;
+
+  //
+  // TRUE if the PCI bus driver creates the handle for this PCI device
+  //
+  BOOLEAN                                   Registered;
+
+  //
+  // TRUE if the PCI bus driver successfully allocates the resource required by
+  // this PCI device
+  //
+  BOOLEAN                                   Allocated;
+
+  //
+  // The attribute this PCI device currently set
+  //
+  UINT64                                    Attributes;
+
+  //
+  // The attributes this PCI device actually supports
+  //
+  UINT64                                    Supports;
+
+  //
+  // The resource decode the bridge supports
+  //
+  UINT32                                    Decodes;
+
+  //
+  // TRUE if the ROM image is from the PCI Option ROM BAR
+  //
+  BOOLEAN                                   EmbeddedRom;
+
+  //
+  // The OptionRom Size
+  //
+  UINT32                                    RomSize;
+
+  //
+  // TRUE if all OpROM (in device or in platform specific position) have been processed
+  //
+  BOOLEAN                                   AllOpRomProcessed;
+
+  //
+  // TRUE if there is any EFI driver in the OptionRom
+  //
+  BOOLEAN                                   BusOverride;
+
+  //
+  // A list tracking reserved resource on a bridge device
+  //
+  LIST_ENTRY                                ReservedResourceList;
+
+  //
+  // A list tracking image handle of platform specific overriding driver
+  //
+  LIST_ENTRY                                OptionRomDriverList;
+
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR         *ResourcePaddingDescriptors;
+  EFI_HPC_PADDING_ATTRIBUTES                PaddingAttributes;
+
+  //
+  // Bus number ranges for a PCI Root Bridge device
+  //
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR         *BusNumberRanges;
+
+  BOOLEAN                                   IsPciExp;
+  //
+  // For SR-IOV
+  //
+  UINT8                                     PciExpressCapabilityOffset;
+  UINT32                                    AriCapabilityOffset;
+  UINT32                                    SrIovCapabilityOffset;
+  UINT32                                    MrIovCapabilityOffset;
+  PCI_BAR                                   VfPciBar[PCI_MAX_BAR];
+  UINT32                                    SystemPageSize;
+  UINT16                                    InitialVFs;
+  UINT16                                    ReservedBusNum;
+  //
+  // Per PCI to PCI Bridge spec, I/O window is 4K aligned,
+  // but some chipsets support non-standard I/O window alignments less than 4K.
+  // This field is used to support this case.
+  //
+  UINT16                                    BridgeIoAlignment;
+  UINT32                                    ResizableBarOffset;
+  UINT32                                    ResizableBarNumber;
+};
+
+#define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
+  CR (a, PCI_IO_DEVICE, PciIo, PCI_IO_DEVICE_SIGNATURE)
+
+#define PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS(a) \
+  CR (a, PCI_IO_DEVICE, PciDriverOverride, PCI_IO_DEVICE_SIGNATURE)
+
+#define PCI_IO_DEVICE_FROM_LINK(a) \
+  CR (a, PCI_IO_DEVICE, Link, PCI_IO_DEVICE_SIGNATURE)
+
+#define PCI_IO_DEVICE_FROM_LOAD_FILE2_THIS(a) \
+  CR (a, PCI_IO_DEVICE, LoadFile2, PCI_IO_DEVICE_SIGNATURE)
+
+
+
+//
+// Global Variables
+//
+extern EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL *gIncompatiblePciDeviceSupport;
+extern EFI_DRIVER_BINDING_PROTOCOL                  gPciBusDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL                  gPciBusComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL                 gPciBusComponentName2;
+extern BOOLEAN                                      gFullEnumeration;
+extern UINTN                                        gPciHostBridgeNumber;
+extern EFI_HANDLE                                   gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];
+extern UINT64                                       gAllOne;
+extern UINT64                                       gAllZero;
+extern EFI_PCI_PLATFORM_PROTOCOL                    *gPciPlatformProtocol;
+extern EFI_PCI_OVERRIDE_PROTOCOL                    *gPciOverrideProtocol;
+extern BOOLEAN                                      mReserveIsaAliases;
+extern BOOLEAN                                      mReserveVgaAliases;
+
+/**
+  Macro that checks whether device is a GFX device.
+
+  @param  _p      Specified device.
+
+  @retval TRUE    Device is a GFX device.
+  @retval FALSE   Device is not a GFX device.
+
+**/
+#define IS_PCI_GFX(_p)     IS_CLASS2 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_OTHER)
+
+/**
+  Test to see if this driver supports ControllerHandle. Any ControllerHandle
+  than contains a gEfiPciRootBridgeIoProtocolGuid protocol can be supported.
+
+  @param  This                Protocol instance pointer.
+  @param  Controller          Handle of device to test.
+  @param  RemainingDevicePath Optional parameter use to pick a specific child
+                              device to start.
+
+  @retval EFI_SUCCESS         This driver supports this device.
+  @retval EFI_ALREADY_STARTED This driver is already running on this device.
+  @retval other               This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  );
+
+/**
+  Start this driver on ControllerHandle and enumerate Pci bus and start
+  all device under PCI bus.
+
+  @param  This                 Protocol instance pointer.
+  @param  Controller           Handle of device to bind driver to.
+  @param  RemainingDevicePath  Optional parameter use to pick a specific child
+                               device to start.
+
+  @retval EFI_SUCCESS          This driver is added to ControllerHandle.
+  @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.
+  @retval other                This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  );
+
+/**
+  Stop this driver on ControllerHandle. Support stopping any child handles
+  created by this driver.
+
+  @param  This              Protocol instance pointer.
+  @param  Controller        Handle of device to stop driver on.
+  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
+                            children is zero stop the entire bus driver.
+  @param  ChildHandleBuffer List of Child Handles to Stop.
+
+  @retval EFI_SUCCESS       This driver is removed ControllerHandle.
+  @retval other             This driver was not removed from this device.
+
+**/
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
+  IN  EFI_HANDLE                    Controller,
+  IN  UINTN                         NumberOfChildren,
+  IN  EFI_HANDLE                    *ChildHandleBuffer
+  );
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
new file mode 100644
index 0000000000..9d999f973b
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
@@ -0,0 +1,112 @@
+## @file
+#  The PCI bus driver will probe all PCI devices and allocate MMIO and IO space for these devices.
+#  Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable hot plug supporting.
+#
+#  Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PciBusDxe
+  MODULE_UNI_FILE                = PciBusDxe.uni
+  FILE_GUID                      = 93B80004-9FB3-11d4-9A3A-0090273FC14D
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = PciBusEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC ARM AARCH64
+#
+#  DRIVER_BINDING                =  gPciBusDriverBinding
+#  COMPONENT_NAME                =  gPciBusComponentName
+#  COMPONENT_NAME2               =  gPciBusComponentName2
+#
+
+[Sources]
+  PciLib.c
+  PciIo.c
+  PciBus.c
+  PciDeviceSupport.c
+  ComponentName.c
+  ComponentName.h
+  PciCommand.c
+  PciResourceSupport.c
+  PciEnumeratorSupport.c
+  PciEnumerator.c
+  PciOptionRomSupport.c
+  PciDriverOverride.c
+  PciPowerManagement.c
+  PciPowerManagement.h
+  PciDriverOverride.h
+  PciRomTable.c
+  PciHotPlugSupport.c
+  PciLib.h
+  PciHotPlugSupport.h
+  PciRomTable.h
+  PciOptionRomSupport.h
+  PciEnumeratorSupport.h
+  PciEnumerator.h
+  PciResourceSupport.h
+  PciDeviceSupport.h
+  PciCommand.h
+  PciIo.h
+  PciBus.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  PcdLib
+  DevicePathLib
+  UefiBootServicesTableLib
+  MemoryAllocationLib
+  ReportStatusCodeLib
+  BaseMemoryLib
+  UefiLib
+  BaseLib
+  UefiDriverEntryPoint
+  DebugLib
+
+[Protocols]
+  gEfiPciHotPlugRequestProtocolGuid               ## SOMETIMES_PRODUCES
+  gEfiPciIoProtocolGuid                           ## BY_START
+  gEfiDevicePathProtocolGuid                      ## BY_START
+  gEfiBusSpecificDriverOverrideProtocolGuid       ## BY_START
+  gEfiLoadedImageProtocolGuid                     ## SOMETIMES_CONSUMES
+  gEfiDecompressProtocolGuid                      ## SOMETIMES_CONSUMES
+  gEfiPciHotPlugInitProtocolGuid                  ## SOMETIMES_CONSUMES
+  gEfiPciHostBridgeResourceAllocationProtocolGuid ## TO_START
+  gEfiPciPlatformProtocolGuid                     ## SOMETIMES_CONSUMES
+  gEfiPciOverrideProtocolGuid                     ## SOMETIMES_CONSUMES
+  gEfiPciEnumerationCompleteProtocolGuid          ## PRODUCES
+  gEfiPciRootBridgeIoProtocolGuid                 ## TO_START
+  gEfiIncompatiblePciDeviceSupportProtocolGuid    ## SOMETIMES_CONSUMES
+  gEfiLoadFile2ProtocolGuid                       ## SOMETIMES_PRODUCES
+  gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
+  gEdkiiDeviceSecurityProtocolGuid                ## SOMETIMES_CONSUMES
+  gEdkiiDeviceIdentifierTypePciGuid               ## SOMETIMES_CONSUMES
+  gEfiLoadedImageDevicePathProtocolGuid           ## CONSUMES
+
+[FeaturePcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport      ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPciBridgeIoAlignmentProbe       ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdUnalignedPciIoEnable            ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPciDegradeResourceForOptionRom  ## CONSUMES
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize         ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSupport                ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport                  ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport                ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration    ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPcieResizableBarSupport     ## CONSUMES
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  PciBusDxeExtra.uni
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.uni b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.uni
new file mode 100644
index 0000000000..81bfc2c9ef
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.uni
@@ -0,0 +1,16 @@
+// /** @file
+// The PCI bus driver will probe all PCI devices and allocate MMIO and IO space for these devices.
+//
+// Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable hot plug supporting.
+//
+// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Probes all PCI devices and allocate MMIO and IO space for these devices"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable hot plug supporting."
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxeExtra.uni b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxeExtra.uni
new file mode 100644
index 0000000000..f6a7cdae00
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxeExtra.uni
@@ -0,0 +1,14 @@
+// /** @file
+// PciBusDxe Localized Strings and Content
+//
+// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"PCI Bus DXE Driver"
+
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.c
new file mode 100644
index 0000000000..3111448643
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.c
@@ -0,0 +1,267 @@
+/** @file
+  PCI command register operations supporting functions implementation for PCI Bus module.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+
+/**
+  Operate the PCI register via PciIo function interface.
+
+  @param PciIoDevice    Pointer to instance of PCI_IO_DEVICE.
+  @param Command        Operator command.
+  @param Offset         The address within the PCI configuration space for the PCI controller.
+  @param Operation      Type of Operation.
+  @param PtrCommand     Return buffer holding old PCI command, if operation is not EFI_SET_REGISTER.
+
+  @return Status of PciIo operation.
+
+**/
+EFI_STATUS
+PciOperateRegister (
+  IN  PCI_IO_DEVICE *PciIoDevice,
+  IN  UINT16        Command,
+  IN  UINT8         Offset,
+  IN  UINT8         Operation,
+  OUT UINT16        *PtrCommand
+  )
+{
+  UINT16              OldCommand;
+  EFI_STATUS          Status;
+  EFI_PCI_IO_PROTOCOL *PciIo;
+
+  OldCommand  = 0;
+  PciIo       = &PciIoDevice->PciIo;
+
+  if (Operation != EFI_SET_REGISTER) {
+    Status = PciIo->Pci.Read (
+                          PciIo,
+                          EfiPciIoWidthUint16,
+                          Offset,
+                          1,
+                          &OldCommand
+                          );
+
+    if (Operation == EFI_GET_REGISTER) {
+      *PtrCommand = OldCommand;
+      return Status;
+    }
+  }
+
+  if (Operation == EFI_ENABLE_REGISTER) {
+    OldCommand = (UINT16) (OldCommand | Command);
+  } else if (Operation == EFI_DISABLE_REGISTER) {
+    OldCommand = (UINT16) (OldCommand & ~(Command));
+  } else {
+    OldCommand = Command;
+  }
+
+  return PciIo->Pci.Write (
+                      PciIo,
+                      EfiPciIoWidthUint16,
+                      Offset,
+                      1,
+                      &OldCommand
+                      );
+}
+
+/**
+  Check the capability supporting by given device.
+
+  @param PciIoDevice   Pointer to instance of PCI_IO_DEVICE.
+
+  @retval TRUE         Capability supported.
+  @retval FALSE        Capability not supported.
+
+**/
+BOOLEAN
+PciCapabilitySupport (
+  IN PCI_IO_DEVICE  *PciIoDevice
+  )
+{
+  if ((PciIoDevice->Pci.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) != 0) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  Locate capability register block per capability ID.
+
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.
+  @param CapId             The capability ID.
+  @param Offset            A pointer to the offset returned.
+  @param NextRegBlock      A pointer to the next block returned.
+
+  @retval EFI_SUCCESS      Successfully located capability register block.
+  @retval EFI_UNSUPPORTED  Pci device does not support capability.
+  @retval EFI_NOT_FOUND    Pci device support but can not find register block.
+
+**/
+EFI_STATUS
+LocateCapabilityRegBlock (
+  IN PCI_IO_DEVICE  *PciIoDevice,
+  IN UINT8          CapId,
+  IN OUT UINT8      *Offset,
+  OUT UINT8         *NextRegBlock OPTIONAL
+  )
+{
+  UINT8   CapabilityPtr;
+  UINT16  CapabilityEntry;
+  UINT8   CapabilityID;
+
+  //
+  // To check the capability of this device supports
+  //
+  if (!PciCapabilitySupport (PciIoDevice)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (*Offset != 0) {
+    CapabilityPtr = *Offset;
+  } else {
+
+    CapabilityPtr = 0;
+    if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+
+      PciIoDevice->PciIo.Pci.Read (
+                               &PciIoDevice->PciIo,
+                               EfiPciIoWidthUint8,
+                               EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR,
+                               1,
+                               &CapabilityPtr
+                               );
+    } else {
+
+      PciIoDevice->PciIo.Pci.Read (
+                               &PciIoDevice->PciIo,
+                               EfiPciIoWidthUint8,
+                               PCI_CAPBILITY_POINTER_OFFSET,
+                               1,
+                               &CapabilityPtr
+                               );
+    }
+  }
+
+  while ((CapabilityPtr >= 0x40) && ((CapabilityPtr & 0x03) == 0x00)) {
+    PciIoDevice->PciIo.Pci.Read (
+                             &PciIoDevice->PciIo,
+                             EfiPciIoWidthUint16,
+                             CapabilityPtr,
+                             1,
+                             &CapabilityEntry
+                             );
+
+    CapabilityID = (UINT8) CapabilityEntry;
+
+    if (CapabilityID == CapId) {
+      *Offset = CapabilityPtr;
+      if (NextRegBlock != NULL) {
+        *NextRegBlock = (UINT8) (CapabilityEntry >> 8);
+      }
+
+      return EFI_SUCCESS;
+    }
+
+    //
+    // Certain PCI device may incorrectly have capability pointing to itself,
+    // break to avoid dead loop.
+    //
+    if (CapabilityPtr == (UINT8) (CapabilityEntry >> 8)) {
+      break;
+    }
+
+    CapabilityPtr = (UINT8) (CapabilityEntry >> 8);
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Locate PciExpress capability register block per capability ID.
+
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.
+  @param CapId             The capability ID.
+  @param Offset            A pointer to the offset returned.
+  @param NextRegBlock      A pointer to the next block returned.
+
+  @retval EFI_SUCCESS      Successfully located capability register block.
+  @retval EFI_UNSUPPORTED  Pci device does not support capability.
+  @retval EFI_NOT_FOUND    Pci device support but can not find register block.
+
+**/
+EFI_STATUS
+LocatePciExpressCapabilityRegBlock (
+  IN     PCI_IO_DEVICE *PciIoDevice,
+  IN     UINT16        CapId,
+  IN OUT UINT32        *Offset,
+     OUT UINT32        *NextRegBlock OPTIONAL
+  )
+{
+  EFI_STATUS           Status;
+  UINT32               CapabilityPtr;
+  UINT32               CapabilityEntry;
+  UINT16               CapabilityID;
+
+  //
+  // To check the capability of this device supports
+  //
+  if (!PciIoDevice->IsPciExp) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (*Offset != 0) {
+    CapabilityPtr = *Offset;
+  } else {
+    CapabilityPtr = EFI_PCIE_CAPABILITY_BASE_OFFSET;
+  }
+
+  while (CapabilityPtr != 0) {
+    //
+    // Mask it to DWORD alignment per PCI spec
+    //
+    CapabilityPtr &= 0xFFC;
+    Status = PciIoDevice->PciIo.Pci.Read (
+                                      &PciIoDevice->PciIo,
+                                      EfiPciIoWidthUint32,
+                                      CapabilityPtr,
+                                      1,
+                                      &CapabilityEntry
+                                      );
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+
+    if (CapabilityEntry == MAX_UINT32) {
+      DEBUG ((
+        DEBUG_WARN,
+        "%a: [%02x|%02x|%02x] failed to access config space at offset 0x%x\n",
+        __FUNCTION__,
+        PciIoDevice->BusNumber,
+        PciIoDevice->DeviceNumber,
+        PciIoDevice->FunctionNumber,
+        CapabilityPtr
+        ));
+      break;
+    }
+
+    CapabilityID = (UINT16) CapabilityEntry;
+
+    if (CapabilityID == CapId) {
+      *Offset = CapabilityPtr;
+      if (NextRegBlock != NULL) {
+        *NextRegBlock = (CapabilityEntry >> 20) & 0xFFF;
+      }
+
+      return EFI_SUCCESS;
+    }
+
+    CapabilityPtr = (CapabilityEntry >> 20) & 0xFFF;
+  }
+
+  return EFI_NOT_FOUND;
+}
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.h
new file mode 100644
index 0000000000..5eabd56bf2
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.h
@@ -0,0 +1,232 @@
+/** @file
+  PCI command register operations supporting functions declaration for PCI Bus module.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#ifndef _EFI_PCI_COMMAND_H_
+#define _EFI_PCI_COMMAND_H_
+
+//
+// The PCI Command register bits owned by PCI Bus driver.
+//
+// They should be cleared at the beginning. The other registers
+// are owned by chipset, we should not touch them.
+//
+#define EFI_PCI_COMMAND_BITS_OWNED                          ( \
+                EFI_PCI_COMMAND_IO_SPACE                    | \
+                EFI_PCI_COMMAND_MEMORY_SPACE                | \
+                EFI_PCI_COMMAND_BUS_MASTER                  | \
+                EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE | \
+                EFI_PCI_COMMAND_VGA_PALETTE_SNOOP           | \
+                EFI_PCI_COMMAND_FAST_BACK_TO_BACK             \
+                )
+
+//
+// The PCI Bridge Control register bits owned by PCI Bus driver.
+//
+// They should be cleared at the beginning. The other registers
+// are owned by chipset, we should not touch them.
+//
+#define EFI_PCI_BRIDGE_CONTROL_BITS_OWNED                   ( \
+                EFI_PCI_BRIDGE_CONTROL_ISA                  | \
+                EFI_PCI_BRIDGE_CONTROL_VGA                  | \
+                EFI_PCI_BRIDGE_CONTROL_VGA_16               | \
+                EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK      \
+                )
+
+//
+// The PCCard Bridge Control register bits owned by PCI Bus driver.
+//
+// They should be cleared at the beginning. The other registers
+// are owned by chipset, we should not touch them.
+//
+#define EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED                ( \
+                EFI_PCI_BRIDGE_CONTROL_ISA                  | \
+                EFI_PCI_BRIDGE_CONTROL_VGA                  | \
+                EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK      \
+                )
+
+
+#define EFI_GET_REGISTER      1
+#define EFI_SET_REGISTER      2
+#define EFI_ENABLE_REGISTER   3
+#define EFI_DISABLE_REGISTER  4
+
+/**
+  Operate the PCI register via PciIo function interface.
+
+  @param PciIoDevice    Pointer to instance of PCI_IO_DEVICE.
+  @param Command        Operator command.
+  @param Offset         The address within the PCI configuration space for the PCI controller.
+  @param Operation      Type of Operation.
+  @param PtrCommand     Return buffer holding old PCI command, if operation is not EFI_SET_REGISTER.
+
+  @return Status of PciIo operation.
+
+**/
+EFI_STATUS
+PciOperateRegister (
+  IN  PCI_IO_DEVICE *PciIoDevice,
+  IN  UINT16        Command,
+  IN  UINT8         Offset,
+  IN  UINT8         Operation,
+  OUT UINT16        *PtrCommand
+  );
+
+/**
+  Check the capability supporting by given device.
+
+  @param PciIoDevice   Pointer to instance of PCI_IO_DEVICE.
+
+  @retval TRUE         Capability supported.
+  @retval FALSE        Capability not supported.
+
+**/
+BOOLEAN
+PciCapabilitySupport (
+  IN PCI_IO_DEVICE  *PciIoDevice
+  );
+
+/**
+  Locate capability register block per capability ID.
+
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.
+  @param CapId             The capability ID.
+  @param Offset            A pointer to the offset returned.
+  @param NextRegBlock      A pointer to the next block returned.
+
+  @retval EFI_SUCCESS      Successfully located capability register block.
+  @retval EFI_UNSUPPORTED  Pci device does not support capability.
+  @retval EFI_NOT_FOUND    Pci device support but can not find register block.
+
+**/
+EFI_STATUS
+LocateCapabilityRegBlock (
+  IN PCI_IO_DEVICE  *PciIoDevice,
+  IN UINT8          CapId,
+  IN OUT UINT8      *Offset,
+  OUT UINT8         *NextRegBlock OPTIONAL
+  );
+
+/**
+  Locate PciExpress capability register block per capability ID.
+
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.
+  @param CapId             The capability ID.
+  @param Offset            A pointer to the offset returned.
+  @param NextRegBlock      A pointer to the next block returned.
+
+  @retval EFI_SUCCESS      Successfully located capability register block.
+  @retval EFI_UNSUPPORTED  Pci device does not support capability.
+  @retval EFI_NOT_FOUND    Pci device support but can not find register block.
+
+**/
+EFI_STATUS
+LocatePciExpressCapabilityRegBlock (
+  IN     PCI_IO_DEVICE *PciIoDevice,
+  IN     UINT16        CapId,
+  IN OUT UINT32        *Offset,
+     OUT UINT32        *NextRegBlock OPTIONAL
+  );
+
+/**
+  Macro that reads command register.
+
+  @param a[in]            Pointer to instance of PCI_IO_DEVICE.
+  @param b[out]           Pointer to the 16-bit value read from command register.
+
+  @return status of PciIo operation
+
+**/
+#define PCI_READ_COMMAND_REGISTER(a,b) \
+        PciOperateRegister (a, 0, PCI_COMMAND_OFFSET, EFI_GET_REGISTER, b)
+
+/**
+  Macro that writes command register.
+
+  @param a[in]            Pointer to instance of PCI_IO_DEVICE.
+  @param b[in]            The 16-bit value written into command register.
+
+  @return status of PciIo operation
+
+**/
+#define PCI_SET_COMMAND_REGISTER(a,b) \
+        PciOperateRegister (a, b, PCI_COMMAND_OFFSET, EFI_SET_REGISTER, NULL)
+
+/**
+  Macro that enables command register.
+
+  @param a[in]            Pointer to instance of PCI_IO_DEVICE.
+  @param b[in]            The enabled value written into command register.
+
+  @return status of PciIo operation
+
+**/
+#define PCI_ENABLE_COMMAND_REGISTER(a,b) \
+        PciOperateRegister (a, b, PCI_COMMAND_OFFSET, EFI_ENABLE_REGISTER, NULL)
+
+/**
+  Macro that disables command register.
+
+  @param a[in]            Pointer to instance of PCI_IO_DEVICE.
+  @param b[in]            The disabled value written into command register.
+
+  @return status of PciIo operation
+
+**/
+#define PCI_DISABLE_COMMAND_REGISTER(a,b) \
+        PciOperateRegister (a, b, PCI_COMMAND_OFFSET, EFI_DISABLE_REGISTER, NULL)
+
+/**
+  Macro that reads PCI bridge control register.
+
+  @param a[in]            Pointer to instance of PCI_IO_DEVICE.
+  @param b[out]           The 16-bit value read from control register.
+
+  @return status of PciIo operation
+
+**/
+#define PCI_READ_BRIDGE_CONTROL_REGISTER(a,b) \
+        PciOperateRegister (a, 0, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_GET_REGISTER, b)
+
+/**
+  Macro that writes PCI bridge control register.
+
+  @param a[in]            Pointer to instance of PCI_IO_DEVICE.
+  @param b[in]            The 16-bit value written into control register.
+
+  @return status of PciIo operation
+
+**/
+#define PCI_SET_BRIDGE_CONTROL_REGISTER(a,b) \
+        PciOperateRegister (a, b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_SET_REGISTER, NULL)
+
+/**
+  Macro that enables PCI bridge control register.
+
+  @param a[in]            Pointer to instance of PCI_IO_DEVICE.
+  @param b[in]            The enabled value written into command register.
+
+  @return status of PciIo operation
+
+**/
+#define PCI_ENABLE_BRIDGE_CONTROL_REGISTER(a,b) \
+        PciOperateRegister (a, b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_ENABLE_REGISTER, NULL)
+
+/**
+ Macro that disables PCI bridge control register.
+
+  @param a[in]            Pointer to instance of PCI_IO_DEVICE.
+  @param b[in]            The disabled value written into command register.
+
+  @return status of PciIo operation
+
+**/
+#define PCI_DISABLE_BRIDGE_CONTROL_REGISTER(a,b) \
+        PciOperateRegister (a, b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_DISABLE_REGISTER, NULL)
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
new file mode 100644
index 0000000000..7effbd5053
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
@@ -0,0 +1,1056 @@
+/** @file
+  Supporting functions implementation for PCI devices management.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+(C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+
+//
+// This device structure is serviced as a header.
+// Its next field points to the first root bridge device node.
+//
+LIST_ENTRY  mPciDevicePool;
+
+/**
+  Initialize the PCI devices pool.
+
+**/
+VOID
+InitializePciDevicePool (
+  VOID
+  )
+{
+  InitializeListHead (&mPciDevicePool);
+}
+
+/**
+  Insert a root bridge into PCI device pool.
+
+  @param RootBridge     A pointer to the PCI_IO_DEVICE.
+
+**/
+VOID
+InsertRootBridge (
+  IN PCI_IO_DEVICE      *RootBridge
+  )
+{
+  InsertTailList (&mPciDevicePool, &(RootBridge->Link));
+}
+
+/**
+  This function is used to insert a PCI device node under
+  a bridge.
+
+  @param Bridge         The PCI bridge.
+  @param PciDeviceNode  The PCI device needs inserting.
+
+**/
+VOID
+InsertPciDevice (
+  IN PCI_IO_DEVICE      *Bridge,
+  IN PCI_IO_DEVICE      *PciDeviceNode
+  )
+{
+  InsertTailList (&Bridge->ChildList, &(PciDeviceNode->Link));
+  PciDeviceNode->Parent = Bridge;
+}
+
+/**
+  Destroy root bridge and remove it from device tree.
+
+  @param RootBridge     The bridge want to be removed.
+
+**/
+VOID
+DestroyRootBridge (
+  IN PCI_IO_DEVICE      *RootBridge
+  )
+{
+  DestroyPciDeviceTree (RootBridge);
+
+  FreePciDevice (RootBridge);
+}
+
+/**
+  Destroy a pci device node.
+
+  All direct or indirect allocated resource for this node will be freed.
+
+  @param PciIoDevice  A pointer to the PCI_IO_DEVICE to be destroyed.
+
+**/
+VOID
+FreePciDevice (
+  IN PCI_IO_DEVICE    *PciIoDevice
+  )
+{
+  ASSERT (PciIoDevice != NULL);
+  //
+  // Assume all children have been removed underneath this device
+  //
+  if (PciIoDevice->ResourcePaddingDescriptors != NULL) {
+    FreePool (PciIoDevice->ResourcePaddingDescriptors);
+  }
+
+  if (PciIoDevice->DevicePath != NULL) {
+    FreePool (PciIoDevice->DevicePath);
+  }
+
+  if (PciIoDevice->BusNumberRanges != NULL) {
+    FreePool (PciIoDevice->BusNumberRanges);
+  }
+
+  FreePool (PciIoDevice);
+}
+
+/**
+  Destroy all the pci device node under the bridge.
+  Bridge itself is not included.
+
+  @param Bridge      A pointer to the PCI_IO_DEVICE.
+
+**/
+VOID
+DestroyPciDeviceTree (
+  IN PCI_IO_DEVICE      *Bridge
+  )
+{
+  LIST_ENTRY      *CurrentLink;
+  PCI_IO_DEVICE   *Temp;
+
+  while (!IsListEmpty (&Bridge->ChildList)) {
+
+    CurrentLink = Bridge->ChildList.ForwardLink;
+
+    //
+    // Remove this node from the linked list
+    //
+    RemoveEntryList (CurrentLink);
+
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    if (!IsListEmpty (&Temp->ChildList)) {
+      DestroyPciDeviceTree (Temp);
+    }
+
+    FreePciDevice (Temp);
+  }
+}
+
+/**
+  Destroy all device nodes under the root bridge
+  specified by Controller.
+
+  The root bridge itself is also included.
+
+  @param  Controller    Root bridge handle.
+
+  @retval EFI_SUCCESS   Destroy all device nodes successfully.
+  @retval EFI_NOT_FOUND Cannot find any PCI device under specified
+                        root bridge.
+
+**/
+EFI_STATUS
+DestroyRootBridgeByHandle (
+  IN EFI_HANDLE        Controller
+  )
+{
+
+  LIST_ENTRY      *CurrentLink;
+  PCI_IO_DEVICE   *Temp;
+
+  CurrentLink = mPciDevicePool.ForwardLink;
+
+  while (CurrentLink != NULL && CurrentLink != &mPciDevicePool) {
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    if (Temp->Handle == Controller) {
+
+      RemoveEntryList (CurrentLink);
+
+      DestroyPciDeviceTree (Temp);
+
+      FreePciDevice (Temp);
+
+      return EFI_SUCCESS;
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  This function registers the PCI IO device.
+
+  It creates a handle for this PCI IO device (if the handle does not exist), attaches
+  appropriate protocols onto the handle, does necessary initialization, and sets up
+  parent/child relationship with its bus controller.
+
+  @param Controller     An EFI handle for the PCI bus controller.
+  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device to be registered.
+  @param Handle         A pointer to hold the returned EFI handle for the PCI IO device.
+
+  @retval EFI_SUCCESS   The PCI device is successfully registered.
+  @retval other         An error occurred when registering the PCI device.
+
+**/
+EFI_STATUS
+RegisterPciDevice (
+  IN  EFI_HANDLE          Controller,
+  IN  PCI_IO_DEVICE       *PciIoDevice,
+  OUT EFI_HANDLE          *Handle      OPTIONAL
+  )
+{
+  EFI_STATUS          Status;
+  VOID                *PlatformOpRomBuffer;
+  UINTN               PlatformOpRomSize;
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  UINT8               Data8;
+  BOOLEAN             HasEfiImage;
+
+  //
+  // Install the pciio protocol, device path protocol
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &PciIoDevice->Handle,
+                  &gEfiDevicePathProtocolGuid,
+                  PciIoDevice->DevicePath,
+                  &gEfiPciIoProtocolGuid,
+                  &PciIoDevice->PciIo,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Force Interrupt line to "Unknown" or "No Connection"
+  //
+  PciIo = &(PciIoDevice->PciIo);
+  Data8 = PCI_INT_LINE_UNKNOWN;
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &Data8);
+
+  //
+  // Process OpRom
+  //
+  if (!PciIoDevice->AllOpRomProcessed) {
+
+    //
+    // Get the OpRom provided by platform
+    //
+    if (gPciPlatformProtocol != NULL) {
+      Status = gPciPlatformProtocol->GetPciRom (
+                                       gPciPlatformProtocol,
+                                       PciIoDevice->Handle,
+                                       &PlatformOpRomBuffer,
+                                       &PlatformOpRomSize
+                                       );
+      if (!EFI_ERROR (Status)) {
+        PciIoDevice->EmbeddedRom    = FALSE;
+        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
+        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
+        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
+        //
+        // For OpROM read from gPciPlatformProtocol:
+        // Add the Rom Image to internal database for later PCI light enumeration
+        //
+        PciRomAddImageMapping (
+          NULL,
+          PciIoDevice->PciRootBridgeIo->SegmentNumber,
+          PciIoDevice->BusNumber,
+          PciIoDevice->DeviceNumber,
+          PciIoDevice->FunctionNumber,
+          PciIoDevice->PciIo.RomImage,
+          PciIoDevice->PciIo.RomSize
+          );
+      }
+    } else if (gPciOverrideProtocol != NULL) {
+      Status = gPciOverrideProtocol->GetPciRom (
+                                       gPciOverrideProtocol,
+                                       PciIoDevice->Handle,
+                                       &PlatformOpRomBuffer,
+                                       &PlatformOpRomSize
+                                       );
+      if (!EFI_ERROR (Status)) {
+        PciIoDevice->EmbeddedRom    = FALSE;
+        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
+        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
+        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
+        //
+        // For OpROM read from gPciOverrideProtocol:
+        // Add the Rom Image to internal database for later PCI light enumeration
+        //
+        PciRomAddImageMapping (
+          NULL,
+          PciIoDevice->PciRootBridgeIo->SegmentNumber,
+          PciIoDevice->BusNumber,
+          PciIoDevice->DeviceNumber,
+          PciIoDevice->FunctionNumber,
+          PciIoDevice->PciIo.RomImage,
+          PciIoDevice->PciIo.RomSize
+          );
+      }
+    }
+  }
+
+  //
+  // Determine if there are EFI images in the option rom
+  //
+  HasEfiImage = ContainEfiImage (PciIoDevice->PciIo.RomImage, PciIoDevice->PciIo.RomSize);
+
+  if (HasEfiImage) {
+    Status = gBS->InstallMultipleProtocolInterfaces (
+                    &PciIoDevice->Handle,
+                    &gEfiLoadFile2ProtocolGuid,
+                    &PciIoDevice->LoadFile2,
+                    NULL
+                    );
+    if (EFI_ERROR (Status)) {
+      gBS->UninstallMultipleProtocolInterfaces (
+             PciIoDevice->Handle,
+             &gEfiDevicePathProtocolGuid,
+             PciIoDevice->DevicePath,
+             &gEfiPciIoProtocolGuid,
+             &PciIoDevice->PciIo,
+             NULL
+             );
+      return Status;
+    }
+  }
+
+
+  if (!PciIoDevice->AllOpRomProcessed) {
+
+    PciIoDevice->AllOpRomProcessed = TRUE;
+
+    //
+    // Dispatch the EFI OpRom for the PCI device.
+    // The OpRom is got from platform in the above code
+    // or loaded from device in the previous round of bus enumeration
+    //
+    if (HasEfiImage) {
+      ProcessOpRomImage (PciIoDevice);
+    }
+  }
+
+  if (PciIoDevice->BusOverride) {
+    //
+    // Install Bus Specific Driver Override Protocol
+    //
+    Status = gBS->InstallMultipleProtocolInterfaces (
+                    &PciIoDevice->Handle,
+                    &gEfiBusSpecificDriverOverrideProtocolGuid,
+                    &PciIoDevice->PciDriverOverride,
+                    NULL
+                    );
+    if (EFI_ERROR (Status)) {
+      gBS->UninstallMultipleProtocolInterfaces (
+             PciIoDevice->Handle,
+             &gEfiDevicePathProtocolGuid,
+             PciIoDevice->DevicePath,
+             &gEfiPciIoProtocolGuid,
+             &PciIoDevice->PciIo,
+             NULL
+             );
+      if (HasEfiImage) {
+        gBS->UninstallMultipleProtocolInterfaces (
+               PciIoDevice->Handle,
+               &gEfiLoadFile2ProtocolGuid,
+               &PciIoDevice->LoadFile2,
+               NULL
+               );
+      }
+
+      return Status;
+    }
+  }
+
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciRootBridgeIoProtocolGuid,
+                  (VOID **) &(PciIoDevice->PciRootBridgeIo),
+                  gPciBusDriverBinding.DriverBindingHandle,
+                  PciIoDevice->Handle,
+                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (Handle != NULL) {
+    *Handle = PciIoDevice->Handle;
+  }
+
+  //
+  // Indicate the pci device is registered
+  //
+  PciIoDevice->Registered = TRUE;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function is used to remove the whole PCI devices on the specified bridge from
+  the root bridge.
+
+  @param RootBridgeHandle   The root bridge device handle.
+  @param Bridge             The bridge device to be removed.
+
+**/
+VOID
+RemoveAllPciDeviceOnBridge (
+  EFI_HANDLE               RootBridgeHandle,
+  PCI_IO_DEVICE            *Bridge
+  )
+{
+  LIST_ENTRY      *CurrentLink;
+  PCI_IO_DEVICE   *Temp;
+
+  while (!IsListEmpty (&Bridge->ChildList)) {
+
+    CurrentLink = Bridge->ChildList.ForwardLink;
+    Temp        = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    //
+    // Check if the current node has been deregistered before
+    // If it is not, then deregister it
+    //
+    if (Temp->Registered) {
+      DeRegisterPciDevice (RootBridgeHandle, Temp->Handle);
+    }
+
+    //
+    // Remove this node from the linked list
+    //
+    RemoveEntryList (CurrentLink);
+
+    if (!IsListEmpty (&Temp->ChildList)) {
+      RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);
+    }
+
+    FreePciDevice (Temp);
+  }
+}
+
+/**
+  This function is used to de-register the PCI IO device.
+
+  That includes un-installing PciIo protocol from the specified PCI
+  device handle.
+
+  @param Controller    An EFI handle for the PCI bus controller.
+  @param Handle        PCI device handle.
+
+  @retval EFI_SUCCESS  The PCI device is successfully de-registered.
+  @retval other        An error occurred when de-registering the PCI device.
+
+**/
+EFI_STATUS
+DeRegisterPciDevice (
+  IN  EFI_HANDLE                     Controller,
+  IN  EFI_HANDLE                     Handle
+  )
+
+{
+  EFI_PCI_IO_PROTOCOL             *PciIo;
+  EFI_STATUS                      Status;
+  PCI_IO_DEVICE                   *PciIoDevice;
+  PCI_IO_DEVICE                   *Node;
+  LIST_ENTRY                      *CurrentLink;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+  Status = gBS->OpenProtocol (
+                  Handle,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &PciIo,
+                  gPciBusDriverBinding.DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (!EFI_ERROR (Status)) {
+    PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
+
+    //
+    // If it is already de-registered
+    //
+    if (!PciIoDevice->Registered) {
+      return EFI_SUCCESS;
+    }
+
+    //
+    // If it is PPB, first de-register its children
+    //
+
+    if (!IsListEmpty (&PciIoDevice->ChildList)) {
+
+      CurrentLink = PciIoDevice->ChildList.ForwardLink;
+
+      while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
+        Node    = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+        Status  = DeRegisterPciDevice (Controller, Node->Handle);
+
+        if (EFI_ERROR (Status)) {
+          return Status;
+        }
+
+        CurrentLink = CurrentLink->ForwardLink;
+      }
+    }
+
+    //
+    // Close the child handle
+    //
+    Status = gBS->CloseProtocol (
+                    Controller,
+                    &gEfiPciRootBridgeIoProtocolGuid,
+                    gPciBusDriverBinding.DriverBindingHandle,
+                    Handle
+                    );
+
+    //
+    // Un-install the Device Path protocol and PCI I/O protocol
+    // and Bus Specific Driver Override protocol if needed.
+    //
+    if (PciIoDevice->BusOverride) {
+      Status = gBS->UninstallMultipleProtocolInterfaces (
+                      Handle,
+                      &gEfiDevicePathProtocolGuid,
+                      PciIoDevice->DevicePath,
+                      &gEfiPciIoProtocolGuid,
+                      &PciIoDevice->PciIo,
+                      &gEfiBusSpecificDriverOverrideProtocolGuid,
+                      &PciIoDevice->PciDriverOverride,
+                      NULL
+                      );
+    } else {
+      Status = gBS->UninstallMultipleProtocolInterfaces (
+                      Handle,
+                      &gEfiDevicePathProtocolGuid,
+                      PciIoDevice->DevicePath,
+                      &gEfiPciIoProtocolGuid,
+                      &PciIoDevice->PciIo,
+                      NULL
+                      );
+    }
+
+    if (!EFI_ERROR (Status)) {
+      //
+      // Try to uninstall LoadFile2 protocol if exists
+      //
+      Status = gBS->OpenProtocol (
+                      Handle,
+                      &gEfiLoadFile2ProtocolGuid,
+                      NULL,
+                      gPciBusDriverBinding.DriverBindingHandle,
+                      Controller,
+                      EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+                      );
+      if (!EFI_ERROR (Status)) {
+        Status = gBS->UninstallMultipleProtocolInterfaces (
+                        Handle,
+                        &gEfiLoadFile2ProtocolGuid,
+                        &PciIoDevice->LoadFile2,
+                        NULL
+                        );
+      }
+      //
+      // Restore Status
+      //
+      Status = EFI_SUCCESS;
+    }
+
+
+    if (EFI_ERROR (Status)) {
+      gBS->OpenProtocol (
+            Controller,
+            &gEfiPciRootBridgeIoProtocolGuid,
+            (VOID **) &PciRootBridgeIo,
+            gPciBusDriverBinding.DriverBindingHandle,
+            Handle,
+            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+            );
+      return Status;
+    }
+
+    //
+    // The Device Driver should disable this device after disconnect
+    // so the Pci Bus driver will not touch this device any more.
+    // Restore the register field to the original value
+    //
+    PciIoDevice->Registered = FALSE;
+    PciIoDevice->Handle     = NULL;
+  } else {
+
+    //
+    // Handle may be closed before
+    //
+    return EFI_SUCCESS;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Start to manage the PCI device on the specified root bridge or PCI-PCI Bridge.
+
+  @param Controller          The root bridge handle.
+  @param RootBridge          A pointer to the PCI_IO_DEVICE.
+  @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL.
+  @param NumberOfChildren    Children number.
+  @param ChildHandleBuffer   A pointer to the child handle buffer.
+
+  @retval EFI_NOT_READY   Device is not allocated.
+  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
+  @retval EFI_NOT_FOUND   Can not find the specific device.
+  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
+
+**/
+EFI_STATUS
+StartPciDevicesOnBridge (
+  IN EFI_HANDLE                          Controller,
+  IN PCI_IO_DEVICE                       *RootBridge,
+  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
+  IN OUT UINT8                           *NumberOfChildren,
+  IN OUT EFI_HANDLE                      *ChildHandleBuffer
+  )
+
+{
+  PCI_IO_DEVICE             *PciIoDevice;
+  EFI_DEV_PATH_PTR          Node;
+  EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
+  EFI_STATUS                Status;
+  LIST_ENTRY                *CurrentLink;
+  UINT64                    Supports;
+
+  PciIoDevice = NULL;
+  CurrentLink = RootBridge->ChildList.ForwardLink;
+
+  while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList) {
+
+    PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+    if (RemainingDevicePath != NULL) {
+
+      Node.DevPath = RemainingDevicePath;
+
+      if (Node.Pci->Device != PciIoDevice->DeviceNumber ||
+          Node.Pci->Function != PciIoDevice->FunctionNumber) {
+        CurrentLink = CurrentLink->ForwardLink;
+        continue;
+      }
+
+      //
+      // Check if the device has been assigned with required resource
+      //
+      if (!PciIoDevice->Allocated) {
+        return EFI_NOT_READY;
+      }
+
+      //
+      // Check if the current node has been registered before
+      // If it is not, register it
+      //
+      if (!PciIoDevice->Registered) {
+        Status = RegisterPciDevice (
+                   Controller,
+                   PciIoDevice,
+                   NULL
+                   );
+
+      }
+
+      if (NumberOfChildren != NULL && ChildHandleBuffer != NULL && PciIoDevice->Registered) {
+        ChildHandleBuffer[*NumberOfChildren] = PciIoDevice->Handle;
+        (*NumberOfChildren)++;
+      }
+
+      //
+      // Get the next device path
+      //
+      CurrentDevicePath = NextDevicePathNode (RemainingDevicePath);
+      if (IsDevicePathEnd (CurrentDevicePath)) {
+        return EFI_SUCCESS;
+      }
+
+      //
+      // If it is a PPB
+      //
+      if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
+        Status = StartPciDevicesOnBridge (
+                   Controller,
+                   PciIoDevice,
+                   CurrentDevicePath,
+                   NumberOfChildren,
+                   ChildHandleBuffer
+                   );
+
+        PciIoDevice->PciIo.Attributes (
+                             &(PciIoDevice->PciIo),
+                             EfiPciIoAttributeOperationSupported,
+                             0,
+                             &Supports
+                             );
+        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
+        PciIoDevice->PciIo.Attributes (
+                             &(PciIoDevice->PciIo),
+                             EfiPciIoAttributeOperationEnable,
+                             Supports,
+                             NULL
+                             );
+
+        return Status;
+      } else {
+
+        //
+        // Currently, the PCI bus driver only support PCI-PCI bridge
+        //
+        return EFI_UNSUPPORTED;
+      }
+
+    } else {
+
+      //
+      // If remaining device path is NULL,
+      // try to enable all the pci devices under this bridge
+      //
+      if (!PciIoDevice->Registered && PciIoDevice->Allocated) {
+        Status = RegisterPciDevice (
+                   Controller,
+                   PciIoDevice,
+                   NULL
+                   );
+
+      }
+
+      if (NumberOfChildren != NULL && ChildHandleBuffer != NULL && PciIoDevice->Registered) {
+        ChildHandleBuffer[*NumberOfChildren] = PciIoDevice->Handle;
+        (*NumberOfChildren)++;
+      }
+
+      if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
+        Status = StartPciDevicesOnBridge (
+                   Controller,
+                   PciIoDevice,
+                   RemainingDevicePath,
+                   NumberOfChildren,
+                   ChildHandleBuffer
+                   );
+
+        PciIoDevice->PciIo.Attributes (
+                             &(PciIoDevice->PciIo),
+                             EfiPciIoAttributeOperationSupported,
+                             0,
+                             &Supports
+                             );
+        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
+        PciIoDevice->PciIo.Attributes (
+                             &(PciIoDevice->PciIo),
+                             EfiPciIoAttributeOperationEnable,
+                             Supports,
+                             NULL
+                             );
+
+      }
+
+      CurrentLink = CurrentLink->ForwardLink;
+    }
+  }
+
+  if (PciIoDevice == NULL) {
+    return EFI_NOT_FOUND;
+  } else {
+    return EFI_SUCCESS;
+  }
+}
+
+/**
+  Start to manage all the PCI devices it found previously under
+  the entire host bridge.
+
+  @param Controller          The root bridge handle.
+
+  @retval EFI_NOT_READY   Device is not allocated.
+  @retval EFI_SUCCESS     Success to start Pci device on host bridge.
+
+**/
+EFI_STATUS
+StartPciDevices (
+  IN EFI_HANDLE                         Controller
+  )
+{
+  PCI_IO_DEVICE     *RootBridge;
+  EFI_HANDLE        ThisHostBridge;
+  LIST_ENTRY        *CurrentLink;
+
+  RootBridge = GetRootBridgeByHandle (Controller);
+  ASSERT (RootBridge != NULL);
+  ThisHostBridge = RootBridge->PciRootBridgeIo->ParentHandle;
+
+  CurrentLink = mPciDevicePool.ForwardLink;
+
+  while (CurrentLink != NULL && CurrentLink != &mPciDevicePool) {
+
+    RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+    //
+    // Locate the right root bridge to start
+    //
+    if (RootBridge->PciRootBridgeIo->ParentHandle == ThisHostBridge) {
+      StartPciDevicesOnBridge (
+         RootBridge->Handle,
+         RootBridge,
+         NULL,
+         NULL,
+         NULL
+         );
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Create root bridge device.
+
+  @param RootBridgeHandle    Specified root bridge handle.
+
+  @return The crated root bridge device instance, NULL means no
+          root bridge device instance created.
+
+**/
+PCI_IO_DEVICE *
+CreateRootBridge (
+  IN EFI_HANDLE                   RootBridgeHandle
+  )
+{
+  EFI_STATUS                      Status;
+  PCI_IO_DEVICE                   *Dev;
+  EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+  Dev = AllocateZeroPool (sizeof (PCI_IO_DEVICE));
+  if (Dev == NULL) {
+    return NULL;
+  }
+
+  Dev->Signature  = PCI_IO_DEVICE_SIGNATURE;
+  Dev->Handle     = RootBridgeHandle;
+  InitializeListHead (&Dev->ChildList);
+
+  Status = gBS->OpenProtocol (
+                  RootBridgeHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID **) &ParentDevicePath,
+                  gPciBusDriverBinding.DriverBindingHandle,
+                  RootBridgeHandle,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+
+  if (EFI_ERROR (Status)) {
+    FreePool (Dev);
+    return NULL;
+  }
+
+  //
+  // Record the root bridge parent device path
+  //
+  Dev->DevicePath = DuplicateDevicePath (ParentDevicePath);
+
+  //
+  // Get the pci root bridge io protocol
+  //
+  Status = gBS->OpenProtocol (
+                  RootBridgeHandle,
+                  &gEfiPciRootBridgeIoProtocolGuid,
+                  (VOID **) &PciRootBridgeIo,
+                  gPciBusDriverBinding.DriverBindingHandle,
+                  RootBridgeHandle,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+
+  if (EFI_ERROR (Status)) {
+    FreePciDevice (Dev);
+    return NULL;
+  }
+
+  Dev->PciRootBridgeIo = PciRootBridgeIo;
+
+  //
+  // Initialize the PCI I/O instance structure
+  //
+  InitializePciIoInstance (Dev);
+  InitializePciDriverOverrideInstance (Dev);
+  InitializePciLoadFile2 (Dev);
+
+  //
+  // Initialize reserved resource list and
+  // option rom driver list
+  //
+  InitializeListHead (&Dev->ReservedResourceList);
+  InitializeListHead (&Dev->OptionRomDriverList);
+
+  return Dev;
+}
+
+/**
+  Get root bridge device instance by specific root bridge handle.
+
+  @param RootBridgeHandle    Given root bridge handle.
+
+  @return The root bridge device instance, NULL means no root bridge
+          device instance found.
+
+**/
+PCI_IO_DEVICE *
+GetRootBridgeByHandle (
+  EFI_HANDLE RootBridgeHandle
+  )
+{
+  PCI_IO_DEVICE   *RootBridgeDev;
+  LIST_ENTRY      *CurrentLink;
+
+  CurrentLink = mPciDevicePool.ForwardLink;
+
+  while (CurrentLink != NULL && CurrentLink != &mPciDevicePool) {
+
+    RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+    if (RootBridgeDev->Handle == RootBridgeHandle) {
+      return RootBridgeDev;
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return NULL;
+}
+
+/**
+  Judge whether Pci device existed.
+
+  @param Bridge       Parent bridge instance.
+  @param PciIoDevice  Device instance.
+
+  @retval TRUE        Pci device existed.
+  @retval FALSE       Pci device did not exist.
+
+**/
+BOOLEAN
+PciDeviceExisted (
+  IN PCI_IO_DEVICE    *Bridge,
+  IN PCI_IO_DEVICE    *PciIoDevice
+  )
+{
+
+  PCI_IO_DEVICE   *Temp;
+  LIST_ENTRY      *CurrentLink;
+
+  CurrentLink = Bridge->ChildList.ForwardLink;
+
+  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
+
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    if (Temp == PciIoDevice) {
+      return TRUE;
+    }
+
+    if (!IsListEmpty (&Temp->ChildList)) {
+      if (PciDeviceExisted (Temp, PciIoDevice)) {
+        return TRUE;
+      }
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return FALSE;
+}
+
+/**
+  Get the active VGA device on the specified Host Bridge.
+
+  @param HostBridgeHandle    Host Bridge handle.
+
+  @return The active VGA device on the specified Host Bridge.
+
+**/
+PCI_IO_DEVICE *
+LocateVgaDeviceOnHostBridge (
+  IN EFI_HANDLE           HostBridgeHandle
+  )
+{
+  LIST_ENTRY      *CurrentLink;
+  PCI_IO_DEVICE   *PciIoDevice;
+
+  CurrentLink = mPciDevicePool.ForwardLink;
+
+  while (CurrentLink != NULL && CurrentLink != &mPciDevicePool) {
+
+    PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    if (PciIoDevice->PciRootBridgeIo->ParentHandle== HostBridgeHandle) {
+
+      PciIoDevice = LocateVgaDevice (PciIoDevice);
+
+      if (PciIoDevice != NULL) {
+        return PciIoDevice;
+      }
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return NULL;
+}
+
+/**
+  Locate the active VGA device under the bridge.
+
+  @param Bridge  PCI IO instance for the bridge.
+
+  @return The active VGA device.
+
+**/
+PCI_IO_DEVICE *
+LocateVgaDevice (
+  IN PCI_IO_DEVICE        *Bridge
+  )
+{
+  LIST_ENTRY      *CurrentLink;
+  PCI_IO_DEVICE   *PciIoDevice;
+
+  CurrentLink = Bridge->ChildList.ForwardLink;
+
+  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
+
+    PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    if (IS_PCI_VGA(&PciIoDevice->Pci) &&
+        (PciIoDevice->Attributes &
+         (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY |
+          EFI_PCI_IO_ATTRIBUTE_VGA_IO     |
+          EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) != 0) {
+      return PciIoDevice;
+    }
+
+    if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
+
+      PciIoDevice = LocateVgaDevice (PciIoDevice);
+
+      if (PciIoDevice != NULL) {
+        return PciIoDevice;
+      }
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return NULL;
+}
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.h
new file mode 100644
index 0000000000..acc0edc0bb
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.h
@@ -0,0 +1,266 @@
+/** @file
+  Supporting functions declaration for PCI devices management.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_PCI_DEVICE_SUPPORT_H_
+#define _EFI_PCI_DEVICE_SUPPORT_H_
+
+/**
+  Initialize the PCI devices pool.
+
+**/
+VOID
+InitializePciDevicePool (
+  VOID
+  );
+
+/**
+  Insert a root bridge into PCI device pool.
+
+  @param RootBridge     A pointer to the PCI_IO_DEVICE.
+
+**/
+VOID
+InsertRootBridge (
+  IN PCI_IO_DEVICE      *RootBridge
+  );
+
+/**
+  This function is used to insert a PCI device node under
+  a bridge.
+
+  @param Bridge         The PCI bridge.
+  @param PciDeviceNode  The PCI device needs inserting.
+
+**/
+VOID
+InsertPciDevice (
+  IN PCI_IO_DEVICE      *Bridge,
+  IN PCI_IO_DEVICE      *PciDeviceNode
+  );
+
+/**
+  Destroy root bridge and remove it from device tree.
+
+  @param RootBridge     The bridge want to be removed.
+
+**/
+VOID
+DestroyRootBridge (
+  IN PCI_IO_DEVICE      *RootBridge
+  );
+
+/**
+  Destroy all the pci device node under the bridge.
+  Bridge itself is not included.
+
+  @param Bridge         A pointer to the PCI_IO_DEVICE.
+
+**/
+VOID
+DestroyPciDeviceTree (
+  IN PCI_IO_DEVICE      *Bridge
+  );
+
+/**
+  Destroy all device nodes under the root bridge
+  specified by Controller.
+
+  The root bridge itself is also included.
+
+  @param  Controller    Root bridge handle.
+
+  @retval EFI_SUCCESS   Destroy all device nodes successfully.
+  @retval EFI_NOT_FOUND Cannot find any PCI device under specified
+                        root bridge.
+
+**/
+EFI_STATUS
+DestroyRootBridgeByHandle (
+  IN EFI_HANDLE        Controller
+  );
+
+/**
+  This function registers the PCI IO device.
+
+  It creates a handle for this PCI IO device (if the handle does not exist), attaches
+  appropriate protocols onto the handle, does necessary initialization, and sets up
+  parent/child relationship with its bus controller.
+
+  @param Controller     An EFI handle for the PCI bus controller.
+  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device to be registered.
+  @param Handle         A pointer to hold the returned EFI handle for the PCI IO device.
+
+  @retval EFI_SUCCESS   The PCI device is successfully registered.
+  @retval other         An error occurred when registering the PCI device.
+
+**/
+EFI_STATUS
+RegisterPciDevice (
+  IN  EFI_HANDLE          Controller,
+  IN  PCI_IO_DEVICE       *PciIoDevice,
+  OUT EFI_HANDLE          *Handle      OPTIONAL
+  );
+
+/**
+  This function is used to remove the whole PCI devices on the specified bridge from
+  the root bridge.
+
+  @param RootBridgeHandle   The root bridge device handle.
+  @param Bridge             The bridge device to be removed.
+
+**/
+VOID
+RemoveAllPciDeviceOnBridge (
+  EFI_HANDLE               RootBridgeHandle,
+  PCI_IO_DEVICE            *Bridge
+  );
+
+/**
+  This function is used to de-register the PCI IO device.
+
+  That includes un-installing PciIo protocol from the specified PCI
+  device handle.
+
+  @param Controller    An EFI handle for the PCI bus controller.
+  @param Handle        PCI device handle.
+
+  @retval EFI_SUCCESS  The PCI device is successfully de-registered.
+  @retval other        An error occurred when de-registering the PCI device.
+
+**/
+EFI_STATUS
+DeRegisterPciDevice (
+  IN  EFI_HANDLE                     Controller,
+  IN  EFI_HANDLE                     Handle
+  );
+
+/**
+  Start to manage the PCI device on the specified root bridge or PCI-PCI Bridge.
+
+  @param Controller          The root bridge handle.
+  @param RootBridge          A pointer to the PCI_IO_DEVICE.
+  @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL.
+  @param NumberOfChildren    Children number.
+  @param ChildHandleBuffer   A pointer to the child handle buffer.
+
+  @retval EFI_NOT_READY   Device is not allocated.
+  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
+  @retval EFI_NOT_FOUND   Can not find the specific device.
+  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
+
+**/
+EFI_STATUS
+StartPciDevicesOnBridge (
+  IN EFI_HANDLE                          Controller,
+  IN PCI_IO_DEVICE                       *RootBridge,
+  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
+  IN OUT UINT8                           *NumberOfChildren,
+  IN OUT EFI_HANDLE                      *ChildHandleBuffer
+  );
+
+/**
+  Start to manage all the PCI devices it found previously under
+  the entire host bridge.
+
+  @param Controller          The root bridge handle.
+
+  @retval EFI_NOT_READY   Device is not allocated.
+  @retval EFI_SUCCESS     Success to start Pci device on host bridge.
+
+**/
+EFI_STATUS
+StartPciDevices (
+  IN EFI_HANDLE                         Controller
+  );
+
+/**
+  Create root bridge device.
+
+  @param RootBridgeHandle    Specified root bridge handle.
+
+  @return The crated root bridge device instance, NULL means no
+          root bridge device instance created.
+
+**/
+PCI_IO_DEVICE *
+CreateRootBridge (
+  IN EFI_HANDLE                   RootBridgeHandle
+  );
+
+/**
+  Get root bridge device instance by specific root bridge handle.
+
+  @param RootBridgeHandle    Given root bridge handle.
+
+  @return The root bridge device instance, NULL means no root bridge
+          device instance found.
+
+**/
+PCI_IO_DEVICE *
+GetRootBridgeByHandle (
+  EFI_HANDLE RootBridgeHandle
+  );
+
+
+/**
+  Judge whether Pci device existed.
+
+  @param Bridge       Parent bridge instance.
+  @param PciIoDevice  Device instance.
+
+  @retval TRUE        Pci device existed.
+  @retval FALSE       Pci device did not exist.
+
+**/
+BOOLEAN
+PciDeviceExisted (
+  IN PCI_IO_DEVICE    *Bridge,
+  IN PCI_IO_DEVICE    *PciIoDevice
+  );
+
+/**
+  Get the active VGA device on the specified Host Bridge.
+
+  @param HostBridgeHandle    Host Bridge handle.
+
+  @return The active VGA device on the specified Host Bridge.
+
+**/
+PCI_IO_DEVICE *
+LocateVgaDeviceOnHostBridge (
+  IN EFI_HANDLE           HostBridgeHandle
+  );
+
+/**
+  Locate the active VGA device under the bridge.
+
+  @param Bridge  PCI IO instance for the bridge.
+
+  @return The active VGA device.
+
+**/
+PCI_IO_DEVICE *
+LocateVgaDevice (
+  IN PCI_IO_DEVICE        *Bridge
+  );
+
+
+/**
+  Destroy a pci device node.
+
+  All direct or indirect allocated resource for this node will be freed.
+
+  @param PciIoDevice  A pointer to the PCI_IO_DEVICE to be destroyed.
+
+**/
+VOID
+FreePciDevice (
+  IN PCI_IO_DEVICE    *PciIoDevice
+  );
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c
new file mode 100644
index 0000000000..0c3f684c8c
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c
@@ -0,0 +1,188 @@
+/** @file
+  Functions implementation for Bus Specific Driver Override protocol.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+
+/**
+  Initializes a PCI Driver Override Instance.
+
+  @param  PciIoDevice   PCI Device instance.
+
+**/
+VOID
+InitializePciDriverOverrideInstance (
+  IN OUT PCI_IO_DEVICE          *PciIoDevice
+  )
+{
+  PciIoDevice->PciDriverOverride.GetDriver = GetDriver;
+}
+
+/**
+  Find the image handle whose path equals to ImagePath.
+
+  @param ImagePath   Image path.
+
+  @return Image handle.
+**/
+EFI_HANDLE
+LocateImageHandle (
+  IN EFI_DEVICE_PATH_PROTOCOL   *ImagePath
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_HANDLE                    *Handles;
+  UINTN                         Index;
+  UINTN                         HandleNum;
+  EFI_DEVICE_PATH_PROTOCOL      *DevicePath;
+  UINTN                         ImagePathSize;
+  EFI_HANDLE                    ImageHandle;
+
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiLoadedImageDevicePathProtocolGuid,
+                  NULL,
+                  &HandleNum,
+                  &Handles
+                  );
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  ImageHandle   = NULL;
+  ImagePathSize = GetDevicePathSize (ImagePath);
+
+  for (Index = 0; Index < HandleNum; Index++) {
+    Status = gBS->HandleProtocol (Handles[Index], &gEfiLoadedImageDevicePathProtocolGuid, (VOID **) &DevicePath);
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+    if ((ImagePathSize == GetDevicePathSize (DevicePath)) &&
+        (CompareMem (ImagePath, DevicePath, ImagePathSize) == 0)
+        ) {
+      ImageHandle = Handles[Index];
+      break;
+    }
+  }
+
+  FreePool (Handles);
+  return ImageHandle;
+}
+
+/**
+  Uses a bus specific algorithm to retrieve a driver image handle for a controller.
+
+  @param  This                  A pointer to the EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL instance.
+  @param  DriverImageHandle     On input, a pointer to the previous driver image handle returned
+                                by GetDriver(). On output, a pointer to the next driver
+                                image handle. Passing in a NULL, will return the first driver
+                                image handle.
+
+  @retval EFI_SUCCESS           A bus specific override driver is returned in DriverImageHandle.
+  @retval EFI_NOT_FOUND         The end of the list of override drivers was reached.
+                                A bus specific override driver is not returned in DriverImageHandle.
+  @retval EFI_INVALID_PARAMETER DriverImageHandle is not a handle that was returned on a
+                                previous call to GetDriver().
+
+**/
+EFI_STATUS
+EFIAPI
+GetDriver (
+  IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL              *This,
+  IN OUT EFI_HANDLE                                         *DriverImageHandle
+  )
+{
+  PCI_IO_DEVICE             *PciIoDevice;
+  LIST_ENTRY                *Link;
+  PCI_DRIVER_OVERRIDE_LIST  *Override;
+  BOOLEAN                   ReturnNext;
+
+  Override    = NULL;
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS (This);
+  ReturnNext  = (BOOLEAN) (*DriverImageHandle == NULL);
+  for ( Link = GetFirstNode (&PciIoDevice->OptionRomDriverList)
+      ; !IsNull (&PciIoDevice->OptionRomDriverList, Link)
+      ; Link = GetNextNode (&PciIoDevice->OptionRomDriverList, Link)
+      ) {
+
+    Override = DRIVER_OVERRIDE_FROM_LINK (Link);
+
+    if (ReturnNext) {
+      if (Override->DriverImageHandle == NULL) {
+        Override->DriverImageHandle = LocateImageHandle (Override->DriverImagePath);
+      }
+
+      if (Override->DriverImageHandle == NULL) {
+        //
+        // The Option ROM identified by Override->DriverImagePath is not loaded.
+        //
+        continue;
+      } else {
+        *DriverImageHandle = Override->DriverImageHandle;
+        return EFI_SUCCESS;
+      }
+    }
+
+    if (*DriverImageHandle == Override->DriverImageHandle) {
+      ReturnNext = TRUE;
+    }
+  }
+
+  ASSERT (IsNull (&PciIoDevice->OptionRomDriverList, Link));
+  //
+  // ReturnNext indicates a handle match happens.
+  // If all nodes are checked without handle match happening,
+  // the DriverImageHandle should be a invalid handle.
+  //
+  if (ReturnNext) {
+    return EFI_NOT_FOUND;
+  } else {
+    return EFI_INVALID_PARAMETER;
+  }
+}
+
+/**
+  Add an overriding driver image.
+
+  @param PciIoDevice        Instance of PciIo device.
+  @param DriverImageHandle  Image handle of newly added driver image.
+  @param DriverImagePath    Device path of newly added driver image.
+
+  @retval EFI_SUCCESS          Successfully added driver.
+  @retval EFI_OUT_OF_RESOURCES No memory resource for new driver instance.
+  @retval other                Some error occurred when locating gEfiLoadedImageProtocolGuid.
+
+**/
+EFI_STATUS
+AddDriver (
+  IN PCI_IO_DEVICE            *PciIoDevice,
+  IN EFI_HANDLE               DriverImageHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL *DriverImagePath
+  )
+{
+  PCI_DRIVER_OVERRIDE_LIST      *Node;
+
+  //
+  // Caller should pass in either Image Handle or Image Path, but not both.
+  //
+  ASSERT ((DriverImageHandle == NULL) || (DriverImagePath == NULL));
+
+  Node = AllocateZeroPool (sizeof (PCI_DRIVER_OVERRIDE_LIST));
+  if (Node == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Node->Signature         = DRIVER_OVERRIDE_SIGNATURE;
+  Node->DriverImageHandle = DriverImageHandle;
+  Node->DriverImagePath   = DuplicateDevicePath (DriverImagePath);
+
+  InsertTailList (&PciIoDevice->OptionRomDriverList, &Node->Link);
+
+  PciIoDevice->BusOverride  = TRUE;
+  return EFI_SUCCESS;
+}
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.h
new file mode 100644
index 0000000000..ab058fa762
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.h
@@ -0,0 +1,83 @@
+/** @file
+  Functions declaration for Bus Specific Driver Override protocol.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#ifndef _EFI_PCI_DRIVER_OVERRRIDE_H_
+#define _EFI_PCI_DRIVER_OVERRRIDE_H_
+
+#define DRIVER_OVERRIDE_SIGNATURE SIGNATURE_32 ('d', 'r', 'o', 'v')
+
+//
+// PCI driver override driver image list
+//
+typedef struct {
+  UINT32                   Signature;
+  LIST_ENTRY               Link;
+  EFI_HANDLE               DriverImageHandle;
+  EFI_DEVICE_PATH_PROTOCOL *DriverImagePath;
+} PCI_DRIVER_OVERRIDE_LIST;
+
+
+#define DRIVER_OVERRIDE_FROM_LINK(a) \
+  CR (a, PCI_DRIVER_OVERRIDE_LIST, Link, DRIVER_OVERRIDE_SIGNATURE)
+
+/**
+  Initializes a PCI Driver Override Instance.
+
+  @param  PciIoDevice   PCI Device instance.
+
+**/
+VOID
+InitializePciDriverOverrideInstance (
+  IN OUT PCI_IO_DEVICE          *PciIoDevice
+  );
+
+/**
+  Add an overriding driver image.
+
+  @param PciIoDevice        Instance of PciIo device.
+  @param DriverImageHandle  Image handle of newly added driver image.
+  @param DriverImagePath    Device path of newly added driver image.
+
+  @retval EFI_SUCCESS          Successfully added driver.
+  @retval EFI_OUT_OF_RESOURCES No memory resource for new driver instance.
+  @retval other                Some error occurred when locating gEfiLoadedImageProtocolGuid.
+
+**/
+EFI_STATUS
+AddDriver (
+  IN PCI_IO_DEVICE            *PciIoDevice,
+  IN EFI_HANDLE               DriverImageHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL *DriverImagePath
+  );
+
+
+/**
+  Uses a bus specific algorithm to retrieve a driver image handle for a controller.
+
+  @param  This                  A pointer to the EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL instance.
+  @param  DriverImageHandle     On input, a pointer to the previous driver image handle returned
+                                by GetDriver(). On output, a pointer to the next driver
+                                image handle. Passing in a NULL, will return the first driver
+                                image handle.
+
+  @retval EFI_SUCCESS           A bus specific override driver is returned in DriverImageHandle.
+  @retval EFI_NOT_FOUND         The end of the list of override drivers was reached.
+                                A bus specific override driver is not returned in DriverImageHandle.
+  @retval EFI_INVALID_PARAMETER DriverImageHandle is not a handle that was returned on a
+                                previous call to GetDriver().
+
+**/
+EFI_STATUS
+EFIAPI
+GetDriver (
+  IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL              *This,
+  IN OUT EFI_HANDLE                                         *DriverImageHandle
+  );
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
new file mode 100644
index 0000000000..4e1c328b7e
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
@@ -0,0 +1,2210 @@
+/** @file
+  PCI eunmeration implementation on entire PCI bus system for PCI Bus module.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+
+/**
+  This routine is used to enumerate entire pci bus system
+  in a given platform.
+
+  @param Controller          Parent controller handle.
+  @param HostBridgeHandle    Host bridge handle.
+
+  @retval EFI_SUCCESS    PCI enumeration finished successfully.
+  @retval other          Some error occurred when enumerating the pci bus system.
+
+**/
+EFI_STATUS
+PciEnumerator (
+  IN EFI_HANDLE                    Controller,
+  IN EFI_HANDLE                    HostBridgeHandle
+  )
+{
+  EFI_STATUS                                        Status;
+  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc;
+
+  //
+  // Get the pci host bridge resource allocation protocol
+  //
+  Status = gBS->OpenProtocol (
+                  HostBridgeHandle,
+                  &gEfiPciHostBridgeResourceAllocationProtocolGuid,
+                  (VOID **) &PciResAlloc,
+                  gPciBusDriverBinding.DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Notify the pci bus enumeration is about to begin
+  //
+  Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Start the bus allocation phase
+  //
+  Status = PciHostBridgeEnumerator (PciResAlloc);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Submit the resource request
+  //
+  Status = PciHostBridgeResourceAllocator (PciResAlloc);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Notify the pci bus enumeration is about to complete
+  //
+  Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeEndEnumeration);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Process P2C
+  //
+  Status = PciHostBridgeP2CProcess (PciResAlloc);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Process attributes for devices on this host bridge
+  //
+  Status = PciHostBridgeDeviceAttribute (PciResAlloc);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Enumerate PCI root bridge.
+
+  @param PciResAlloc   Pointer to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
+  @param RootBridgeDev Instance of root bridge device.
+
+  @retval EFI_SUCCESS  Successfully enumerated root bridge.
+  @retval other        Failed to enumerate root bridge.
+
+**/
+EFI_STATUS
+PciRootBridgeEnumerator (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc,
+  IN PCI_IO_DEVICE                                     *RootBridgeDev
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration1;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration2;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration3;
+  UINT8                             SubBusNumber;
+  UINT8                             StartBusNumber;
+  UINT8                             PaddedBusRange;
+  EFI_HANDLE                        RootBridgeHandle;
+  UINT8                             Desc;
+  UINT64                            AddrLen;
+  UINT64                            AddrRangeMin;
+
+  SubBusNumber    = 0;
+  StartBusNumber  = 0;
+  PaddedBusRange  = 0;
+
+  //
+  // Get the root bridge handle
+  //
+  RootBridgeHandle = RootBridgeDev->Handle;
+
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+    EFI_PROGRESS_CODE,
+    EFI_IO_BUS_PCI | EFI_IOB_PCI_BUS_ENUM,
+    RootBridgeDev->DevicePath
+    );
+
+  //
+  // Get the Bus information
+  //
+  Status = PciResAlloc->StartBusEnumeration (
+                          PciResAlloc,
+                          RootBridgeHandle,
+                          (VOID **) &Configuration
+                          );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (Configuration == NULL || Configuration->Desc == ACPI_END_TAG_DESCRIPTOR) {
+    return EFI_INVALID_PARAMETER;
+  }
+  RootBridgeDev->BusNumberRanges = Configuration;
+
+  //
+  // Sort the descriptors in ascending order
+  //
+  for (Configuration1 = Configuration; Configuration1->Desc != ACPI_END_TAG_DESCRIPTOR; Configuration1++) {
+    Configuration2 = Configuration1;
+    for (Configuration3 = Configuration1 + 1; Configuration3->Desc != ACPI_END_TAG_DESCRIPTOR; Configuration3++) {
+      if (Configuration2->AddrRangeMin > Configuration3->AddrRangeMin) {
+        Configuration2 = Configuration3;
+      }
+    }
+    //
+    // All other fields other than AddrRangeMin and AddrLen are ignored in a descriptor,
+    // so only need to swap these two fields.
+    //
+    if (Configuration2 != Configuration1) {
+      AddrRangeMin = Configuration1->AddrRangeMin;
+      Configuration1->AddrRangeMin = Configuration2->AddrRangeMin;
+      Configuration2->AddrRangeMin = AddrRangeMin;
+
+      AddrLen = Configuration1->AddrLen;
+      Configuration1->AddrLen = Configuration2->AddrLen;
+      Configuration2->AddrLen = AddrLen;
+    }
+  }
+
+  //
+  // Get the bus number to start with
+  //
+  StartBusNumber = (UINT8) (Configuration->AddrRangeMin);
+
+  //
+  // Initialize the subordinate bus number
+  //
+  SubBusNumber = StartBusNumber;
+
+  //
+  // Reset all assigned PCI bus number
+  //
+  ResetAllPpbBusNumber (
+    RootBridgeDev,
+    StartBusNumber
+  );
+
+  //
+  // Assign bus number
+  //
+  Status = PciScanBus (
+            RootBridgeDev,
+            StartBusNumber,
+            &SubBusNumber,
+            &PaddedBusRange
+            );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+
+  //
+  // Assign max bus number scanned
+  //
+
+  Status = PciAllocateBusNumber (RootBridgeDev, SubBusNumber, PaddedBusRange, &SubBusNumber);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Find the bus range which contains the higest bus number, then returns the number of buses
+  // that should be decoded.
+  //
+  while (Configuration->AddrRangeMin + Configuration->AddrLen - 1 < SubBusNumber) {
+    Configuration++;
+  }
+  AddrLen = Configuration->AddrLen;
+  Configuration->AddrLen = SubBusNumber - Configuration->AddrRangeMin + 1;
+
+  //
+  // Save the Desc field of the next descriptor. Mark the next descriptor as an END descriptor.
+  //
+  Configuration++;
+  Desc = Configuration->Desc;
+  Configuration->Desc = ACPI_END_TAG_DESCRIPTOR;
+
+  //
+  // Set bus number
+  //
+  Status = PciResAlloc->SetBusNumbers (
+                          PciResAlloc,
+                          RootBridgeHandle,
+                          RootBridgeDev->BusNumberRanges
+                          );
+
+  //
+  // Restore changed fields
+  //
+  Configuration->Desc = Desc;
+  (Configuration - 1)->AddrLen = AddrLen;
+
+  return Status;
+}
+
+/**
+  This routine is used to process all PCI devices' Option Rom
+  on a certain root bridge.
+
+  @param Bridge     Given parent's root bridge.
+  @param RomBase    Base address of ROM driver loaded from.
+  @param MaxLength  Maximum rom size.
+
+**/
+VOID
+ProcessOptionRom (
+  IN PCI_IO_DEVICE *Bridge,
+  IN UINT64        RomBase,
+  IN UINT64        MaxLength
+  )
+{
+  LIST_ENTRY      *CurrentLink;
+  PCI_IO_DEVICE   *Temp;
+
+  //
+  // Go through bridges to reach all devices
+  //
+  CurrentLink = Bridge->ChildList.ForwardLink;
+  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+    if (!IsListEmpty (&Temp->ChildList)) {
+
+      //
+      // Go further to process the option rom under this bridge
+      //
+      ProcessOptionRom (Temp, RomBase, MaxLength);
+    }
+
+    if (Temp->RomSize != 0 && Temp->RomSize <= MaxLength) {
+
+      //
+      // Load and process the option rom
+      //
+      LoadOpRomImage (Temp, RomBase);
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+}
+
+/**
+  This routine is used to assign bus number to the given PCI bus system
+
+  @param Bridge             Parent root bridge instance.
+  @param StartBusNumber     Number of beginning.
+  @param SubBusNumber       The number of sub bus.
+
+  @retval EFI_SUCCESS       Successfully assigned bus number.
+  @retval EFI_DEVICE_ERROR  Failed to assign bus number.
+
+**/
+EFI_STATUS
+PciAssignBusNumber (
+  IN PCI_IO_DEVICE                      *Bridge,
+  IN UINT8                              StartBusNumber,
+  OUT UINT8                             *SubBusNumber
+  )
+{
+  EFI_STATUS                      Status;
+  PCI_TYPE00                      Pci;
+  UINT8                           Device;
+  UINT8                           Func;
+  UINT64                          Address;
+  UINTN                           SecondBus;
+  UINT16                          Register;
+  UINT8                           Register8;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+  PciRootBridgeIo = Bridge->PciRootBridgeIo;
+
+  SecondBus       = 0;
+  Register        = 0;
+
+  *SubBusNumber = StartBusNumber;
+
+  //
+  // First check to see whether the parent is ppb
+  //
+  for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+
+      //
+      // Check to see whether a pci device is present
+      //
+      Status = PciDevicePresent (
+                PciRootBridgeIo,
+                &Pci,
+                StartBusNumber,
+                Device,
+                Func
+                );
+
+      if (EFI_ERROR (Status) && Func == 0) {
+        //
+        // go to next device if there is no Function 0
+        //
+        break;
+      }
+
+      if (!EFI_ERROR (Status)   &&
+          (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
+
+        //
+        // Reserved one bus for cardbus bridge
+        //
+        Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);
+        if (EFI_ERROR (Status)) {
+          return Status;
+        }
+        SecondBus = *SubBusNumber;
+
+        Register  = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
+
+        Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
+
+        Status = PciRootBridgeIo->Pci.Write (
+                                        PciRootBridgeIo,
+                                        EfiPciWidthUint16,
+                                        Address,
+                                        1,
+                                        &Register
+                                        );
+
+        //
+        // Initialize SubBusNumber to SecondBus
+        //
+        Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
+        Status = PciRootBridgeIo->Pci.Write (
+                                        PciRootBridgeIo,
+                                        EfiPciWidthUint8,
+                                        Address,
+                                        1,
+                                        SubBusNumber
+                                        );
+        //
+        // If it is PPB, resursively search down this bridge
+        //
+        if (IS_PCI_BRIDGE (&Pci)) {
+
+          Register8 = 0xFF;
+          Status = PciRootBridgeIo->Pci.Write (
+                                          PciRootBridgeIo,
+                                          EfiPciWidthUint8,
+                                          Address,
+                                          1,
+                                          &Register8
+                                          );
+
+          Status = PciAssignBusNumber (
+                    Bridge,
+                    (UINT8) (SecondBus),
+                    SubBusNumber
+                    );
+
+          if (EFI_ERROR (Status)) {
+            return EFI_DEVICE_ERROR;
+          }
+        }
+
+        //
+        // Set the current maximum bus number under the PPB
+        //
+        Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
+
+        Status = PciRootBridgeIo->Pci.Write (
+                                        PciRootBridgeIo,
+                                        EfiPciWidthUint8,
+                                        Address,
+                                        1,
+                                        SubBusNumber
+                                        );
+
+      }
+
+      if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
+
+        //
+        // Skip sub functions, this is not a multi function device
+        //
+        Func = PCI_MAX_FUNC;
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This routine is used to determine the root bridge attribute by interfacing
+  the host bridge resource allocation protocol.
+
+  @param PciResAlloc    Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+  @param RootBridgeDev  Root bridge instance
+
+  @retval EFI_SUCCESS  Successfully got root bridge's attribute.
+  @retval other        Failed to get attribute.
+
+**/
+EFI_STATUS
+DetermineRootBridgeAttributes (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
+  IN PCI_IO_DEVICE                                    *RootBridgeDev
+  )
+{
+  UINT64      Attributes;
+  EFI_STATUS  Status;
+  EFI_HANDLE  RootBridgeHandle;
+
+  Attributes        = 0;
+  RootBridgeHandle  = RootBridgeDev->Handle;
+
+  //
+  // Get root bridge attribute by calling into pci host bridge resource allocation protocol
+  //
+  Status = PciResAlloc->GetAllocAttributes (
+                          PciResAlloc,
+                          RootBridgeHandle,
+                          &Attributes
+                          );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Here is the point where PCI bus driver calls HOST bridge allocation protocol
+  // Currently we hardcoded for ea815
+  //
+  if ((Attributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) {
+    RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED;
+  }
+
+  if ((Attributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0) {
+    RootBridgeDev->Decodes |= EFI_BRIDGE_MEM64_DECODE_SUPPORTED;
+    RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
+  }
+
+  RootBridgeDev->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
+  RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
+  RootBridgeDev->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get Max Option Rom size on specified bridge.
+
+  @param Bridge    Given bridge device instance.
+
+  @return Max size of option rom needed.
+
+**/
+UINT32
+GetMaxOptionRomSize (
+  IN PCI_IO_DEVICE   *Bridge
+  )
+{
+  LIST_ENTRY      *CurrentLink;
+  PCI_IO_DEVICE   *Temp;
+  UINT32          MaxOptionRomSize;
+  UINT32          TempOptionRomSize;
+
+  MaxOptionRomSize = 0;
+
+  //
+  // Go through bridges to reach all devices
+  //
+  CurrentLink = Bridge->ChildList.ForwardLink;
+  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+    if (!IsListEmpty (&Temp->ChildList)) {
+
+      //
+      // Get max option rom size under this bridge
+      //
+      TempOptionRomSize = GetMaxOptionRomSize (Temp);
+
+      //
+      // Compare with the option rom size of the bridge
+      // Get the larger one
+      //
+      if (Temp->RomSize > TempOptionRomSize) {
+        TempOptionRomSize = Temp->RomSize;
+      }
+
+    } else {
+
+      //
+      // For devices get the rom size directly
+      //
+      TempOptionRomSize = Temp->RomSize;
+    }
+
+    //
+    // Get the largest rom size on this bridge
+    //
+    if (TempOptionRomSize > MaxOptionRomSize) {
+      MaxOptionRomSize = TempOptionRomSize;
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return MaxOptionRomSize;
+}
+
+/**
+  Process attributes of devices on this host bridge
+
+  @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
+
+  @retval EFI_SUCCESS   Successfully process attribute.
+  @retval EFI_NOT_FOUND Can not find the specific root bridge device.
+  @retval other         Failed to determine the root bridge device's attribute.
+
+**/
+EFI_STATUS
+PciHostBridgeDeviceAttribute (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+  )
+{
+  EFI_HANDLE    RootBridgeHandle;
+  PCI_IO_DEVICE *RootBridgeDev;
+  EFI_STATUS    Status;
+
+  RootBridgeHandle = NULL;
+
+  while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+    //
+    // Get RootBridg Device by handle
+    //
+    RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+
+    if (RootBridgeDev == NULL) {
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // Set the attributes for devcies behind the Root Bridge
+    //
+    Status = DetermineDeviceAttribute (RootBridgeDev);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get resource allocation status from the ACPI resource descriptor.
+
+  @param AcpiConfig       Point to Acpi configuration table.
+  @param IoResStatus      Return the status of I/O resource.
+  @param Mem32ResStatus   Return the status of 32-bit Memory resource.
+  @param PMem32ResStatus  Return the status of 32-bit Prefetchable Memory resource.
+  @param Mem64ResStatus   Return the status of 64-bit Memory resource.
+  @param PMem64ResStatus  Return the status of 64-bit Prefetchable Memory resource.
+
+**/
+VOID
+GetResourceAllocationStatus (
+  VOID        *AcpiConfig,
+  OUT UINT64  *IoResStatus,
+  OUT UINT64  *Mem32ResStatus,
+  OUT UINT64  *PMem32ResStatus,
+  OUT UINT64  *Mem64ResStatus,
+  OUT UINT64  *PMem64ResStatus
+  )
+{
+  UINT8                             *Temp;
+  UINT64                            ResStatus;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ACPIAddressDesc;
+
+  Temp = (UINT8 *) AcpiConfig;
+
+  while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+
+    ACPIAddressDesc       = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
+    ResStatus = ACPIAddressDesc->AddrTranslationOffset;
+
+    switch (ACPIAddressDesc->ResType) {
+    case 0:
+      if (ACPIAddressDesc->AddrSpaceGranularity == 32) {
+        if (ACPIAddressDesc->SpecificFlag == 0x06) {
+          //
+          // Pmem32
+          //
+          *PMem32ResStatus = ResStatus;
+        } else {
+          //
+          // Mem32
+          //
+          *Mem32ResStatus = ResStatus;
+        }
+      }
+
+      if (ACPIAddressDesc->AddrSpaceGranularity == 64) {
+        if (ACPIAddressDesc->SpecificFlag == 0x06) {
+          //
+          // PMem64
+          //
+          *PMem64ResStatus = ResStatus;
+        } else {
+          //
+          // Mem64
+          //
+          *Mem64ResStatus = ResStatus;
+        }
+      }
+
+      break;
+
+    case 1:
+      //
+      // Io
+      //
+      *IoResStatus = ResStatus;
+      break;
+
+    default:
+      break;
+    }
+
+    Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+  }
+}
+
+/**
+  Remove a PCI device from device pool and mark its bar.
+
+  @param PciDevice Instance of Pci device.
+
+  @retval EFI_SUCCESS Successfully remove the PCI device.
+  @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge.
+
+**/
+EFI_STATUS
+RejectPciDevice (
+  IN PCI_IO_DEVICE       *PciDevice
+  )
+{
+  PCI_IO_DEVICE   *Bridge;
+  PCI_IO_DEVICE   *Temp;
+  LIST_ENTRY      *CurrentLink;
+
+  //
+  // Remove the padding resource from a bridge
+  //
+  if ( IS_PCI_BRIDGE(&PciDevice->Pci) &&
+       PciDevice->ResourcePaddingDescriptors != NULL ) {
+    FreePool (PciDevice->ResourcePaddingDescriptors);
+    PciDevice->ResourcePaddingDescriptors = NULL;
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Skip RB and PPB
+  //
+  if (IS_PCI_BRIDGE (&PciDevice->Pci) || (PciDevice->Parent == NULL)) {
+    return EFI_ABORTED;
+  }
+
+  if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) {
+    //
+    // Get the root bridge device
+    //
+    Bridge = PciDevice;
+    while (Bridge->Parent != NULL) {
+      Bridge = Bridge->Parent;
+    }
+
+    RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice);
+
+    //
+    // Mark its bar
+    //
+    InitializeP2C (PciDevice);
+  }
+
+  //
+  // Remove the device
+  //
+  Bridge      = PciDevice->Parent;
+  CurrentLink = Bridge->ChildList.ForwardLink;
+  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+    if (Temp == PciDevice) {
+      InitializePciDevice (Temp);
+      RemoveEntryList (CurrentLink);
+      return EFI_SUCCESS;
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return EFI_ABORTED;
+}
+
+/**
+  Determine whethter a PCI device can be rejected.
+
+  @param  PciResNode Pointer to Pci resource node instance.
+
+  @retval TRUE  The PCI device can be rejected.
+  @retval TRUE  The PCI device cannot be rejected.
+
+**/
+BOOLEAN
+IsRejectiveDevice (
+  IN  PCI_RESOURCE_NODE   *PciResNode
+  )
+{
+  PCI_IO_DEVICE *Temp;
+
+  Temp = PciResNode->PciDev;
+
+  //
+  // Ensure the device is present
+  //
+  if (Temp == NULL) {
+    return FALSE;
+  }
+
+  //
+  // PPB and RB should go ahead
+  //
+  if (IS_PCI_BRIDGE (&Temp->Pci) || (Temp->Parent == NULL)) {
+    return TRUE;
+  }
+
+  //
+  // Skip device on Bus0
+  //
+  if ((Temp->Parent != NULL) && (Temp->BusNumber == 0)) {
+    return FALSE;
+  }
+
+  //
+  // Skip VGA
+  //
+  if (IS_PCI_VGA (&Temp->Pci)) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+  Compare two resource nodes and get the larger resource consumer.
+
+  @param PciResNode1  resource node 1 want to be compared
+  @param PciResNode2  resource node 2 want to be compared
+
+  @return Larger resource node.
+
+**/
+PCI_RESOURCE_NODE *
+GetLargerConsumerDevice (
+  IN  PCI_RESOURCE_NODE   *PciResNode1,
+  IN  PCI_RESOURCE_NODE   *PciResNode2
+  )
+{
+  if (PciResNode2 == NULL) {
+    return PciResNode1;
+  }
+
+  if ((IS_PCI_BRIDGE(&(PciResNode2->PciDev->Pci)) || (PciResNode2->PciDev->Parent == NULL)) \
+       && (PciResNode2->ResourceUsage != PciResUsagePadding) )
+  {
+    return PciResNode1;
+  }
+
+  if (PciResNode1 == NULL) {
+    return PciResNode2;
+  }
+
+  if ((PciResNode1->Length) > (PciResNode2->Length)) {
+    return PciResNode1;
+  }
+
+  return PciResNode2;
+}
+
+
+/**
+  Get the max resource consumer in the host resource pool.
+
+  @param ResPool  Pointer to resource pool node.
+
+  @return The max resource consumer in the host resource pool.
+
+**/
+PCI_RESOURCE_NODE *
+GetMaxResourceConsumerDevice (
+  IN  PCI_RESOURCE_NODE   *ResPool
+  )
+{
+  PCI_RESOURCE_NODE *Temp;
+  LIST_ENTRY        *CurrentLink;
+  PCI_RESOURCE_NODE *PciResNode;
+  PCI_RESOURCE_NODE *PPBResNode;
+
+  PciResNode  = NULL;
+
+  CurrentLink = ResPool->ChildList.ForwardLink;
+  while (CurrentLink != NULL && CurrentLink != &ResPool->ChildList) {
+
+    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+    if (!IsRejectiveDevice (Temp)) {
+      CurrentLink = CurrentLink->ForwardLink;
+      continue;
+    }
+
+    if ((IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (Temp->PciDev->Parent == NULL)) \
+          && (Temp->ResourceUsage != PciResUsagePadding))
+    {
+      PPBResNode  = GetMaxResourceConsumerDevice (Temp);
+      PciResNode  = GetLargerConsumerDevice (PciResNode, PPBResNode);
+    } else {
+      PciResNode = GetLargerConsumerDevice (PciResNode, Temp);
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return PciResNode;
+}
+
+/**
+  Adjust host bridge allocation so as to reduce resource requirement
+
+  @param IoPool           Pointer to instance of I/O resource Node.
+  @param Mem32Pool        Pointer to instance of 32-bit memory resource Node.
+  @param PMem32Pool       Pointer to instance of 32-bit Prefetchable memory resource node.
+  @param Mem64Pool        Pointer to instance of 64-bit memory resource node.
+  @param PMem64Pool       Pointer to instance of 64-bit Prefetchable memory resource node.
+  @param IoResStatus      Status of I/O resource Node.
+  @param Mem32ResStatus   Status of 32-bit memory resource Node.
+  @param PMem32ResStatus  Status of 32-bit Prefetchable memory resource node.
+  @param Mem64ResStatus   Status of 64-bit memory resource node.
+  @param PMem64ResStatus  Status of 64-bit Prefetchable memory resource node.
+
+  @retval EFI_SUCCESS     Successfully adjusted resource on host bridge.
+  @retval EFI_ABORTED     Host bridge hasn't this resource type or no resource be adjusted.
+
+**/
+EFI_STATUS
+PciHostBridgeAdjustAllocation (
+  IN  PCI_RESOURCE_NODE   *IoPool,
+  IN  PCI_RESOURCE_NODE   *Mem32Pool,
+  IN  PCI_RESOURCE_NODE   *PMem32Pool,
+  IN  PCI_RESOURCE_NODE   *Mem64Pool,
+  IN  PCI_RESOURCE_NODE   *PMem64Pool,
+  IN  UINT64              IoResStatus,
+  IN  UINT64              Mem32ResStatus,
+  IN  UINT64              PMem32ResStatus,
+  IN  UINT64              Mem64ResStatus,
+  IN  UINT64              PMem64ResStatus
+  )
+{
+  BOOLEAN                               AllocationAjusted;
+  PCI_RESOURCE_NODE                     *PciResNode;
+  PCI_RESOURCE_NODE                     *ResPool[5];
+  PCI_IO_DEVICE                         *RemovedPciDev[5];
+  UINT64                                ResStatus[5];
+  UINTN                                 RemovedPciDevNum;
+  UINTN                                 DevIndex;
+  UINTN                                 ResType;
+  EFI_STATUS                            Status;
+  EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;
+
+  PciResNode = NULL;
+  ZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *));
+  RemovedPciDevNum  = 0;
+
+  ResPool[0]        = IoPool;
+  ResPool[1]        = Mem32Pool;
+  ResPool[2]        = PMem32Pool;
+  ResPool[3]        = Mem64Pool;
+  ResPool[4]        = PMem64Pool;
+
+  ResStatus[0]      = IoResStatus;
+  ResStatus[1]      = Mem32ResStatus;
+  ResStatus[2]      = PMem32ResStatus;
+  ResStatus[3]      = Mem64ResStatus;
+  ResStatus[4]      = PMem64ResStatus;
+
+  AllocationAjusted = FALSE;
+
+  for (ResType = 0; ResType < 5; ResType++) {
+
+    if (ResStatus[ResType] == EFI_RESOURCE_SATISFIED) {
+      continue;
+    }
+
+    if (ResStatus[ResType] == EFI_RESOURCE_NOT_SATISFIED) {
+      //
+      // Host bridge hasn't this resource type
+      //
+      return EFI_ABORTED;
+    }
+
+    //
+    // Hostbridge hasn't enough resource
+    //
+    PciResNode = GetMaxResourceConsumerDevice (ResPool[ResType]);
+    if (PciResNode == NULL) {
+      continue;
+    }
+
+    //
+    // Check if the device has been removed before
+    //
+    for (DevIndex = 0; DevIndex < RemovedPciDevNum; DevIndex++) {
+      if (PciResNode->PciDev == RemovedPciDev[DevIndex]) {
+        break;
+      }
+    }
+
+    if (DevIndex != RemovedPciDevNum) {
+      continue;
+    }
+
+    //
+    // Remove the device if it isn't in the array
+    //
+    Status = RejectPciDevice (PciResNode->PciDev);
+    if (Status == EFI_SUCCESS) {
+      DEBUG ((
+        EFI_D_ERROR,
+        "PciBus: [%02x|%02x|%02x] was rejected due to resource confliction.\n",
+        PciResNode->PciDev->BusNumber, PciResNode->PciDev->DeviceNumber, PciResNode->PciDev->FunctionNumber
+        ));
+
+      //
+      // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
+      //
+      //
+      // Have no way to get ReqRes, AllocRes & Bar here
+      //
+      ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
+      AllocFailExtendedData.DevicePathSize = (UINT16) sizeof (EFI_DEVICE_PATH_PROTOCOL);
+      AllocFailExtendedData.DevicePath     = (UINT8 *) PciResNode->PciDev->DevicePath;
+      AllocFailExtendedData.Bar            = PciResNode->Bar;
+
+      REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
+            EFI_PROGRESS_CODE,
+            EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
+            (VOID *) &AllocFailExtendedData,
+            sizeof (AllocFailExtendedData)
+            );
+
+      //
+      // Add it to the array and indicate at least a device has been rejected
+      //
+      RemovedPciDev[RemovedPciDevNum++] = PciResNode->PciDev;
+      AllocationAjusted                 = TRUE;
+    }
+  }
+  //
+  // End for
+  //
+
+  if (AllocationAjusted) {
+    return EFI_SUCCESS;
+  } else {
+    return EFI_ABORTED;
+  }
+}
+
+/**
+  Summary requests for all resource type, and construct ACPI resource
+  requestor instance.
+
+  @param Bridge           detecting bridge
+  @param IoNode           Pointer to instance of I/O resource Node
+  @param Mem32Node        Pointer to instance of 32-bit memory resource Node
+  @param PMem32Node       Pointer to instance of 32-bit Pmemory resource node
+  @param Mem64Node        Pointer to instance of 64-bit memory resource node
+  @param PMem64Node       Pointer to instance of 64-bit Pmemory resource node
+  @param Config           Output buffer holding new constructed APCI resource requestor
+
+  @retval EFI_SUCCESS           Successfully constructed ACPI resource.
+  @retval EFI_OUT_OF_RESOURCES  No memory available.
+
+**/
+EFI_STATUS
+ConstructAcpiResourceRequestor (
+  IN PCI_IO_DEVICE      *Bridge,
+  IN PCI_RESOURCE_NODE  *IoNode,
+  IN PCI_RESOURCE_NODE  *Mem32Node,
+  IN PCI_RESOURCE_NODE  *PMem32Node,
+  IN PCI_RESOURCE_NODE  *Mem64Node,
+  IN PCI_RESOURCE_NODE  *PMem64Node,
+  OUT VOID              **Config
+  )
+{
+  UINT8                             NumConfig;
+  UINT8                             Aperture;
+  UINT8                             *Configuration;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+  EFI_ACPI_END_TAG_DESCRIPTOR       *PtrEnd;
+
+  NumConfig = 0;
+  Aperture  = 0;
+
+  *Config  = NULL;
+
+  //
+  // if there is io request, add to the io aperture
+  //
+  if (ResourceRequestExisted (IoNode)) {
+    NumConfig++;
+    Aperture |= 0x01;
+  }
+
+  //
+  // if there is mem32 request, add to the mem32 aperture
+  //
+  if (ResourceRequestExisted (Mem32Node)) {
+    NumConfig++;
+    Aperture |= 0x02;
+  }
+
+  //
+  // if there is pmem32 request, add to the pmem32 aperture
+  //
+  if (ResourceRequestExisted (PMem32Node)) {
+    NumConfig++;
+    Aperture |= 0x04;
+  }
+
+  //
+  // if there is mem64 request, add to the mem64 aperture
+  //
+  if (ResourceRequestExisted (Mem64Node)) {
+    NumConfig++;
+    Aperture |= 0x08;
+  }
+
+  //
+  // if there is pmem64 request, add to the pmem64 aperture
+  //
+  if (ResourceRequestExisted (PMem64Node)) {
+    NumConfig++;
+    Aperture |= 0x10;
+  }
+
+  if (NumConfig != 0) {
+
+    //
+    // If there is at least one type of resource request,
+    // allocate a acpi resource node
+    //
+    Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+    if (Configuration == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
+
+    //
+    // Deal with io aperture
+    //
+    if ((Aperture & 0x01) != 0) {
+      Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+      Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
+      //
+      // Io
+      //
+      Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_IO;
+      //
+      // non ISA range
+      //
+      Ptr->SpecificFlag = 1;
+      Ptr->AddrLen      = IoNode->Length;
+      Ptr->AddrRangeMax = IoNode->Alignment;
+
+      Ptr++;
+    }
+    //
+    // Deal with mem32 aperture
+    //
+    if ((Aperture & 0x02) != 0) {
+      Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+      Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
+      //
+      // Mem
+      //
+      Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;
+      //
+      // Nonprefechable
+      //
+      Ptr->SpecificFlag = 0;
+      //
+      // 32 bit
+      //
+      Ptr->AddrSpaceGranularity = 32;
+      Ptr->AddrLen      = Mem32Node->Length;
+      Ptr->AddrRangeMax = Mem32Node->Alignment;
+
+      Ptr++;
+    }
+
+    //
+    // Deal with Pmem32 aperture
+    //
+    if ((Aperture & 0x04) != 0) {
+      Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+      Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
+      //
+      // Mem
+      //
+      Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;
+      //
+      // prefechable
+      //
+      Ptr->SpecificFlag = 0x6;
+      //
+      // 32 bit
+      //
+      Ptr->AddrSpaceGranularity = 32;
+      Ptr->AddrLen      = PMem32Node->Length;
+      Ptr->AddrRangeMax = PMem32Node->Alignment;
+
+      Ptr++;
+    }
+    //
+    // Deal with mem64 aperture
+    //
+    if ((Aperture & 0x08) != 0) {
+      Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+      Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
+      //
+      // Mem
+      //
+      Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;
+      //
+      // nonprefechable
+      //
+      Ptr->SpecificFlag = 0;
+      //
+      // 64 bit
+      //
+      Ptr->AddrSpaceGranularity = 64;
+      Ptr->AddrLen      = Mem64Node->Length;
+      Ptr->AddrRangeMax = Mem64Node->Alignment;
+
+      Ptr++;
+    }
+    //
+    // Deal with Pmem64 aperture
+    //
+    if ((Aperture & 0x10) != 0) {
+      Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+      Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
+      //
+      // Mem
+      //
+      Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;
+      //
+      // prefechable
+      //
+      Ptr->SpecificFlag = 0x06;
+      //
+      // 64 bit
+      //
+      Ptr->AddrSpaceGranularity = 64;
+      Ptr->AddrLen      = PMem64Node->Length;
+      Ptr->AddrRangeMax = PMem64Node->Alignment;
+
+      Ptr++;
+    }
+
+    //
+    // put the checksum
+    //
+    PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr;
+
+    PtrEnd->Desc      = ACPI_END_TAG_DESCRIPTOR;
+    PtrEnd->Checksum  = 0;
+
+  } else {
+
+    //
+    // If there is no resource request
+    //
+    Configuration = AllocateZeroPool (sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+    if (Configuration == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Configuration);
+    PtrEnd->Desc      = ACPI_END_TAG_DESCRIPTOR;
+    PtrEnd->Checksum  = 0;
+  }
+
+  *Config = Configuration;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get resource base from an acpi configuration descriptor.
+
+  @param Config       An acpi configuration descriptor.
+  @param IoBase       Output of I/O resource base address.
+  @param Mem32Base    Output of 32-bit memory base address.
+  @param PMem32Base   Output of 32-bit prefetchable memory base address.
+  @param Mem64Base    Output of 64-bit memory base address.
+  @param PMem64Base   Output of 64-bit prefetchable memory base address.
+
+**/
+VOID
+GetResourceBase (
+  IN VOID     *Config,
+  OUT UINT64  *IoBase,
+  OUT UINT64  *Mem32Base,
+  OUT UINT64  *PMem32Base,
+  OUT UINT64  *Mem64Base,
+  OUT UINT64  *PMem64Base
+  )
+{
+  UINT8                             *Temp;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+  UINT64                            ResStatus;
+
+  ASSERT (Config != NULL);
+
+  *IoBase     = 0xFFFFFFFFFFFFFFFFULL;
+  *Mem32Base  = 0xFFFFFFFFFFFFFFFFULL;
+  *PMem32Base = 0xFFFFFFFFFFFFFFFFULL;
+  *Mem64Base  = 0xFFFFFFFFFFFFFFFFULL;
+  *PMem64Base = 0xFFFFFFFFFFFFFFFFULL;
+
+  Temp        = (UINT8 *) Config;
+
+  while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+
+    Ptr       = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
+    ResStatus = Ptr->AddrTranslationOffset;
+
+    if (ResStatus == EFI_RESOURCE_SATISFIED) {
+
+      switch (Ptr->ResType) {
+
+      //
+      // Memory type aperture
+      //
+      case 0:
+
+        //
+        // Check to see the granularity
+        //
+        if (Ptr->AddrSpaceGranularity == 32) {
+          if ((Ptr->SpecificFlag & 0x06) != 0) {
+            *PMem32Base = Ptr->AddrRangeMin;
+          } else {
+            *Mem32Base = Ptr->AddrRangeMin;
+          }
+        }
+
+        if (Ptr->AddrSpaceGranularity == 64) {
+          if ((Ptr->SpecificFlag & 0x06) != 0) {
+            *PMem64Base = Ptr->AddrRangeMin;
+          } else {
+            *Mem64Base = Ptr->AddrRangeMin;
+          }
+        }
+        break;
+
+      case 1:
+
+        //
+        // Io type aperture
+        //
+        *IoBase = Ptr->AddrRangeMin;
+        break;
+
+      default:
+        break;
+
+      }
+      //
+      // End switch
+      //
+    }
+    //
+    // End for
+    //
+    Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+  }
+}
+
+/**
+  Enumerate pci bridge, allocate resource and determine attribute
+  for devices on this bridge.
+
+  @param BridgeDev    Pointer to instance of bridge device.
+
+  @retval EFI_SUCCESS Successfully enumerated PCI bridge.
+  @retval other       Failed to enumerate.
+
+**/
+EFI_STATUS
+PciBridgeEnumerator (
+  IN PCI_IO_DEVICE                                     *BridgeDev
+  )
+{
+  UINT8               SubBusNumber;
+  UINT8               StartBusNumber;
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  EFI_STATUS          Status;
+
+  SubBusNumber    = 0;
+  StartBusNumber  = 0;
+  PciIo           = &(BridgeDev->PciIo);
+  Status          = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = PciAssignBusNumber (
+            BridgeDev,
+            StartBusNumber,
+            &SubBusNumber
+            );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = PciBridgeResourceAllocator (BridgeDev);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = DetermineDeviceAttribute (BridgeDev);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+
+}
+
+/**
+  Allocate all kinds of resource for PCI bridge.
+
+  @param  Bridge      Pointer to bridge instance.
+
+  @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.
+  @retval other       Failed to allocate resource for bridge.
+
+**/
+EFI_STATUS
+PciBridgeResourceAllocator (
+  IN PCI_IO_DEVICE  *Bridge
+  )
+{
+  PCI_RESOURCE_NODE *IoBridge;
+  PCI_RESOURCE_NODE *Mem32Bridge;
+  PCI_RESOURCE_NODE *PMem32Bridge;
+  PCI_RESOURCE_NODE *Mem64Bridge;
+  PCI_RESOURCE_NODE *PMem64Bridge;
+  UINT64            IoBase;
+  UINT64            Mem32Base;
+  UINT64            PMem32Base;
+  UINT64            Mem64Base;
+  UINT64            PMem64Base;
+  EFI_STATUS        Status;
+
+  IoBridge = CreateResourceNode (
+               Bridge,
+               0,
+               Bridge->BridgeIoAlignment,
+               0,
+               PciBarTypeIo16,
+               PciResUsageTypical
+               );
+
+  Mem32Bridge = CreateResourceNode (
+                  Bridge,
+                  0,
+                  0xFFFFF,
+                  0,
+                  PciBarTypeMem32,
+                  PciResUsageTypical
+                  );
+
+  PMem32Bridge = CreateResourceNode (
+                   Bridge,
+                   0,
+                   0xFFFFF,
+                   0,
+                   PciBarTypePMem32,
+                   PciResUsageTypical
+                   );
+
+  Mem64Bridge = CreateResourceNode (
+                  Bridge,
+                  0,
+                  0xFFFFF,
+                  0,
+                  PciBarTypeMem64,
+                  PciResUsageTypical
+                  );
+
+  PMem64Bridge = CreateResourceNode (
+                   Bridge,
+                   0,
+                   0xFFFFF,
+                   0,
+                   PciBarTypePMem64,
+                   PciResUsageTypical
+                   );
+
+  //
+  // Create resourcemap by going through all the devices subject to this root bridge
+  //
+  CreateResourceMap (
+    Bridge,
+    IoBridge,
+    Mem32Bridge,
+    PMem32Bridge,
+    Mem64Bridge,
+    PMem64Bridge
+    );
+
+  Status = GetResourceBaseFromBridge (
+             Bridge,
+             &IoBase,
+             &Mem32Base,
+             &PMem32Base,
+             &Mem64Base,
+             &PMem64Base
+             );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Program IO resources
+  //
+  ProgramResource (
+    IoBase,
+    IoBridge
+    );
+
+  //
+  // Program Mem32 resources
+  //
+  ProgramResource (
+    Mem32Base,
+    Mem32Bridge
+    );
+
+  //
+  // Program PMem32 resources
+  //
+  ProgramResource (
+    PMem32Base,
+    PMem32Bridge
+    );
+
+  //
+  // Program Mem64 resources
+  //
+  ProgramResource (
+    Mem64Base,
+    Mem64Bridge
+    );
+
+  //
+  // Program PMem64 resources
+  //
+  ProgramResource (
+    PMem64Base,
+    PMem64Bridge
+    );
+
+  DestroyResourceTree (IoBridge);
+  DestroyResourceTree (Mem32Bridge);
+  DestroyResourceTree (PMem32Bridge);
+  DestroyResourceTree (PMem64Bridge);
+  DestroyResourceTree (Mem64Bridge);
+
+  gBS->FreePool (IoBridge);
+  gBS->FreePool (Mem32Bridge);
+  gBS->FreePool (PMem32Bridge);
+  gBS->FreePool (PMem64Bridge);
+  gBS->FreePool (Mem64Bridge);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get resource base address for a pci bridge device.
+
+  @param Bridge     Given Pci driver instance.
+  @param IoBase     Output for base address of I/O type resource.
+  @param Mem32Base  Output for base address of 32-bit memory type resource.
+  @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.
+  @param Mem64Base  Output for base address of 64-bit memory type resource.
+  @param PMem64Base Output for base address of 64-bit Pmemory type resource.
+
+  @retval EFI_SUCCESS           Successfully got resource base address.
+  @retval EFI_OUT_OF_RESOURCES  PCI bridge is not available.
+
+**/
+EFI_STATUS
+GetResourceBaseFromBridge (
+  IN  PCI_IO_DEVICE *Bridge,
+  OUT UINT64        *IoBase,
+  OUT UINT64        *Mem32Base,
+  OUT UINT64        *PMem32Base,
+  OUT UINT64        *Mem64Base,
+  OUT UINT64        *PMem64Base
+  )
+{
+  if (!Bridge->Allocated) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  *IoBase     = gAllOne;
+  *Mem32Base  = gAllOne;
+  *PMem32Base = gAllOne;
+  *Mem64Base  = gAllOne;
+  *PMem64Base = gAllOne;
+
+  if (IS_PCI_BRIDGE (&Bridge->Pci)) {
+
+    if (Bridge->PciBar[PPB_IO_RANGE].Length > 0) {
+      *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;
+    }
+
+    if (Bridge->PciBar[PPB_MEM32_RANGE].Length > 0) {
+      *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;
+    }
+
+    if (Bridge->PciBar[PPB_PMEM32_RANGE].Length > 0) {
+      *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;
+    }
+
+    if (Bridge->PciBar[PPB_PMEM64_RANGE].Length > 0) {
+      *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;
+    } else {
+      *PMem64Base = gAllOne;
+    }
+
+  }
+
+  if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {
+    if (Bridge->PciBar[P2C_IO_1].Length > 0) {
+      *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;
+    } else {
+      if (Bridge->PciBar[P2C_IO_2].Length > 0) {
+        *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;
+      }
+    }
+
+    if (Bridge->PciBar[P2C_MEM_1].Length > 0) {
+      if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {
+        *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
+      }
+
+      if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {
+        *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
+      }
+    }
+
+    if (Bridge->PciBar[P2C_MEM_2].Length > 0) {
+      if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {
+        *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
+      }
+
+      if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {
+        *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+   These are the notifications from the PCI bus driver that it is about to enter a certain
+   phase of the PCI enumeration process.
+
+   This member function can be used to notify the host bridge driver to perform specific actions,
+   including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
+   Eight notification points are defined at this time. See belows:
+   EfiPciHostBridgeBeginEnumeration       Resets the host bridge PCI apertures and internal data
+                                          structures. The PCI enumerator should issue this notification
+                                          before starting a fresh enumeration process. Enumeration cannot
+                                          be restarted after sending any other notification such as
+                                          EfiPciHostBridgeBeginBusAllocation.
+   EfiPciHostBridgeBeginBusAllocation     The bus allocation phase is about to begin. No specific action is
+                                          required here. This notification can be used to perform any
+                                          chipset-specific programming.
+   EfiPciHostBridgeEndBusAllocation       The bus allocation and bus programming phase is complete. No
+                                          specific action is required here. This notification can be used to
+                                          perform any chipset-specific programming.
+   EfiPciHostBridgeBeginResourceAllocation
+                                          The resource allocation phase is about to begin. No specific
+                                          action is required here. This notification can be used to perform
+                                          any chipset-specific programming.
+   EfiPciHostBridgeAllocateResources      Allocates resources per previously submitted requests for all the PCI
+                                          root bridges. These resource settings are returned on the next call to
+                                          GetProposedResources(). Before calling NotifyPhase() with a Phase of
+                                          EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
+                                          for gathering I/O and memory requests for
+                                          all the PCI root bridges and submitting these requests using
+                                          SubmitResources(). This function pads the resource amount
+                                          to suit the root bridge hardware, takes care of dependencies between
+                                          the PCI root bridges, and calls the Global Coherency Domain (GCD)
+                                          with the allocation request. In the case of padding, the allocated range
+                                          could be bigger than what was requested.
+   EfiPciHostBridgeSetResources           Programs the host bridge hardware to decode previously allocated
+                                          resources (proposed resources) for all the PCI root bridges. After the
+                                          hardware is programmed, reassigning resources will not be supported.
+                                          The bus settings are not affected.
+   EfiPciHostBridgeFreeResources          Deallocates resources that were previously allocated for all the PCI
+                                          root bridges and resets the I/O and memory apertures to their initial
+                                          state. The bus settings are not affected. If the request to allocate
+                                          resources fails, the PCI enumerator can use this notification to
+                                          deallocate previous resources, adjust the requests, and retry
+                                          allocation.
+   EfiPciHostBridgeEndResourceAllocation  The resource allocation phase is completed. No specific action is
+                                          required here. This notification can be used to perform any chipsetspecific
+                                          programming.
+
+   @param[in] PciResAlloc         The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+   @param[in] Phase               The phase during enumeration
+
+   @retval EFI_NOT_READY          This phase cannot be entered at this time. For example, this error
+                                  is valid for a Phase of EfiPciHostBridgeAllocateResources if
+                                  SubmitResources() has not been called for one or more
+                                  PCI root bridges before this call
+   @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error. This error is valid
+                                  for a Phase of EfiPciHostBridgeSetResources.
+   @retval EFI_INVALID_PARAMETER  Invalid phase parameter
+   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
+                                  This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
+                                  previously submitted resource requests cannot be fulfilled or
+                                  were only partially fulfilled.
+   @retval EFI_SUCCESS            The notification was accepted without any errors.
+
+**/
+EFI_STATUS
+NotifyPhase (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
+  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE       Phase
+  )
+{
+  EFI_HANDLE                      HostBridgeHandle;
+  EFI_HANDLE                      RootBridgeHandle;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+  EFI_STATUS                      Status;
+
+  HostBridgeHandle  = NULL;
+  RootBridgeHandle  = NULL;
+  if (gPciPlatformProtocol != NULL) {
+    //
+    // Get Host Bridge Handle.
+    //
+    PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
+
+    //
+    // Get the rootbridge Io protocol to find the host bridge handle
+    //
+    Status = gBS->HandleProtocol (
+                    RootBridgeHandle,
+                    &gEfiPciRootBridgeIoProtocolGuid,
+                    (VOID **) &PciRootBridgeIo
+                    );
+
+    if (EFI_ERROR (Status)) {
+      return EFI_NOT_FOUND;
+    }
+
+    HostBridgeHandle = PciRootBridgeIo->ParentHandle;
+
+    //
+    // Call PlatformPci::PlatformNotify() if the protocol is present.
+    //
+    gPciPlatformProtocol->PlatformNotify (
+                            gPciPlatformProtocol,
+                            HostBridgeHandle,
+                            Phase,
+                            ChipsetEntry
+                            );
+  } else if (gPciOverrideProtocol != NULL){
+    //
+    // Get Host Bridge Handle.
+    //
+    PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
+
+    //
+    // Get the rootbridge Io protocol to find the host bridge handle
+    //
+    Status = gBS->HandleProtocol (
+                    RootBridgeHandle,
+                    &gEfiPciRootBridgeIoProtocolGuid,
+                    (VOID **) &PciRootBridgeIo
+                    );
+
+    if (EFI_ERROR (Status)) {
+      return EFI_NOT_FOUND;
+    }
+
+    HostBridgeHandle = PciRootBridgeIo->ParentHandle;
+
+    //
+    // Call PlatformPci::PhaseNotify() if the protocol is present.
+    //
+    gPciOverrideProtocol->PlatformNotify (
+                            gPciOverrideProtocol,
+                            HostBridgeHandle,
+                            Phase,
+                            ChipsetEntry
+                            );
+  }
+
+  Status = PciResAlloc->NotifyPhase (
+                          PciResAlloc,
+                          Phase
+                          );
+
+  if (gPciPlatformProtocol != NULL) {
+    //
+    // Call PlatformPci::PlatformNotify() if the protocol is present.
+    //
+    gPciPlatformProtocol->PlatformNotify (
+                            gPciPlatformProtocol,
+                            HostBridgeHandle,
+                            Phase,
+                            ChipsetExit
+                            );
+
+  } else if (gPciOverrideProtocol != NULL) {
+    //
+    // Call PlatformPci::PhaseNotify() if the protocol is present.
+    //
+    gPciOverrideProtocol->PlatformNotify (
+                            gPciOverrideProtocol,
+                            HostBridgeHandle,
+                            Phase,
+                            ChipsetExit
+                            );
+  }
+
+  return Status;
+}
+
+/**
+  Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
+  stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
+  PCI controllers before enumeration.
+
+  This function is called during the PCI enumeration process. No specific action is expected from this
+  member function. It allows the host bridge driver to preinitialize individual PCI controllers before
+  enumeration.
+
+  @param Bridge            Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+  @param Bus               The bus number of the pci device.
+  @param Device            The device number of the pci device.
+  @param Func              The function number of the pci device.
+  @param Phase             The phase of the PCI device enumeration.
+
+  @retval EFI_SUCCESS              The requested parameters were returned.
+  @retval EFI_INVALID_PARAMETER    RootBridgeHandle is not a valid root bridge handle.
+  @retval EFI_INVALID_PARAMETER    Phase is not a valid phase that is defined in
+                                   EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
+  @retval EFI_DEVICE_ERROR         Programming failed due to a hardware error. The PCI enumerator should
+                                   not enumerate this device, including its child devices if it is a PCI-to-PCI
+                                   bridge.
+
+**/
+EFI_STATUS
+PreprocessController (
+  IN PCI_IO_DEVICE                                    *Bridge,
+  IN UINT8                                            Bus,
+  IN UINT8                                            Device,
+  IN UINT8                                            Func,
+  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE     Phase
+  )
+{
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS       RootBridgePciAddress;
+  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc;
+  EFI_HANDLE                                        RootBridgeHandle;
+  EFI_HANDLE                                        HostBridgeHandle;
+  EFI_STATUS                                        Status;
+
+  //
+  // Get the host bridge handle
+  //
+  HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;
+
+  //
+  // Get the pci host bridge resource allocation protocol
+  //
+  Status = gBS->OpenProtocol (
+                  HostBridgeHandle,
+                  &gEfiPciHostBridgeResourceAllocationProtocolGuid,
+                  (VOID **) &PciResAlloc,
+                  NULL,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Get Root Brige Handle
+  //
+  while (Bridge->Parent != NULL) {
+    Bridge = Bridge->Parent;
+  }
+
+  RootBridgeHandle                      = Bridge->Handle;
+
+  RootBridgePciAddress.Register         = 0;
+  RootBridgePciAddress.Function         = Func;
+  RootBridgePciAddress.Device           = Device;
+  RootBridgePciAddress.Bus              = Bus;
+  RootBridgePciAddress.ExtendedRegister = 0;
+
+  if (gPciPlatformProtocol != NULL) {
+    //
+    // Call PlatformPci::PrepController() if the protocol is present.
+    //
+    gPciPlatformProtocol->PlatformPrepController (
+                            gPciPlatformProtocol,
+                            HostBridgeHandle,
+                            RootBridgeHandle,
+                            RootBridgePciAddress,
+                            Phase,
+                            ChipsetEntry
+                            );
+  } else if (gPciOverrideProtocol != NULL) {
+    //
+    // Call PlatformPci::PrepController() if the protocol is present.
+    //
+    gPciOverrideProtocol->PlatformPrepController (
+                            gPciOverrideProtocol,
+                            HostBridgeHandle,
+                            RootBridgeHandle,
+                            RootBridgePciAddress,
+                            Phase,
+                            ChipsetEntry
+                            );
+  }
+
+  Status = PciResAlloc->PreprocessController (
+                          PciResAlloc,
+                          RootBridgeHandle,
+                          RootBridgePciAddress,
+                          Phase
+                          );
+
+  if (gPciPlatformProtocol != NULL) {
+    //
+    // Call PlatformPci::PrepController() if the protocol is present.
+    //
+    gPciPlatformProtocol->PlatformPrepController (
+                            gPciPlatformProtocol,
+                            HostBridgeHandle,
+                            RootBridgeHandle,
+                            RootBridgePciAddress,
+                            Phase,
+                            ChipsetExit
+                            );
+  } else if (gPciOverrideProtocol != NULL) {
+    //
+    // Call PlatformPci::PrepController() if the protocol is present.
+    //
+    gPciOverrideProtocol->PlatformPrepController (
+                            gPciOverrideProtocol,
+                            HostBridgeHandle,
+                            RootBridgeHandle,
+                            RootBridgePciAddress,
+                            Phase,
+                            ChipsetExit
+                            );
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has
+  happened on the hot-plug controller. Currently, the operations include add operation and remove operation..
+
+  @param This                 A pointer to the hot plug request protocol.
+  @param Operation            The operation the PCI bus driver is requested to make.
+  @param Controller           The handle of the hot-plug controller.
+  @param RemainingDevicePath  The remaining device path for the PCI-like hot-plug device.
+  @param NumberOfChildren     The number of child handles.
+                              For a add operation, it is an output parameter.
+                              For a remove operation, it's an input parameter.
+  @param ChildHandleBuffer    The buffer which contains the child handles.
+
+  @retval EFI_INVALID_PARAMETER  Operation is not a legal value.
+                                 Controller is NULL or not a valid handle.
+                                 NumberOfChildren is NULL.
+                                 ChildHandleBuffer is NULL while Operation is add.
+  @retval EFI_OUT_OF_RESOURCES   There are no enough resources to start the devices.
+  @retval EFI_NOT_FOUND          Can not find bridge according to controller handle.
+  @retval EFI_SUCCESS            The handles for the specified device have been created or destroyed
+                                 as requested, and for an add operation, the new handles are
+                                 returned in ChildHandleBuffer.
+**/
+EFI_STATUS
+EFIAPI
+PciHotPlugRequestNotify (
+  IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,
+  IN EFI_PCI_HOTPLUG_OPERATION        Operation,
+  IN EFI_HANDLE                       Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL         * RemainingDevicePath OPTIONAL,
+  IN OUT UINT8                        *NumberOfChildren,
+  IN OUT EFI_HANDLE                   * ChildHandleBuffer
+  )
+{
+  PCI_IO_DEVICE       *Bridge;
+  PCI_IO_DEVICE       *Temp;
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  UINTN               Index;
+  EFI_HANDLE          RootBridgeHandle;
+  EFI_STATUS          Status;
+
+  //
+  // Check input parameter validity
+  //
+  if ((Controller == NULL) || (NumberOfChildren == NULL)){
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((Operation != EfiPciHotPlugRequestAdd) && (Operation != EfiPciHotplugRequestRemove)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Operation == EfiPciHotPlugRequestAdd){
+    if (ChildHandleBuffer == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+  } else if ((Operation == EfiPciHotplugRequestRemove) && (*NumberOfChildren != 0)) {
+    if (ChildHandleBuffer == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &PciIo,
+                  gPciBusDriverBinding.DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+
+  if (EFI_ERROR (Status)) {
+    return EFI_NOT_FOUND;
+  }
+
+  Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
+
+  //
+  // Get root bridge handle
+  //
+  Temp = Bridge;
+  while (Temp->Parent != NULL) {
+    Temp = Temp->Parent;
+  }
+
+  RootBridgeHandle = Temp->Handle;
+
+  if (Operation == EfiPciHotPlugRequestAdd) {
+    //
+    // Report Status Code to indicate hot plug happens
+    //
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_PROGRESS_CODE,
+      (EFI_IO_BUS_PCI | EFI_IOB_PC_HOTPLUG),
+      Temp->DevicePath
+      );
+
+    if (NumberOfChildren != NULL) {
+      *NumberOfChildren = 0;
+    }
+
+    if (IsListEmpty (&Bridge->ChildList)) {
+
+      Status = PciBridgeEnumerator (Bridge);
+
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+    }
+
+    Status = StartPciDevicesOnBridge (
+              RootBridgeHandle,
+              Bridge,
+              RemainingDevicePath,
+              NumberOfChildren,
+              ChildHandleBuffer
+              );
+
+    return Status;
+  }
+
+  if (Operation == EfiPciHotplugRequestRemove) {
+
+    if (*NumberOfChildren == 0) {
+      //
+      // Remove all devices on the bridge
+      //
+      RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge);
+      return EFI_SUCCESS;
+
+    }
+
+    for (Index = 0; Index < *NumberOfChildren; Index++) {
+      //
+      // De register all the pci device
+      //
+      Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]);
+
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+    }
+    //
+    // End for
+    //
+    return EFI_SUCCESS;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Search hostbridge according to given handle
+
+  @param RootBridgeHandle  Host bridge handle.
+
+  @retval TRUE             Found host bridge handle.
+  @retval FALSE            Not found hot bridge handle.
+
+**/
+BOOLEAN
+SearchHostBridgeHandle (
+  IN EFI_HANDLE RootBridgeHandle
+  )
+{
+  EFI_HANDLE                      HostBridgeHandle;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+  UINTN                           Index;
+  EFI_STATUS                      Status;
+
+  //
+  // Get the rootbridge Io protocol to find the host bridge handle
+  //
+  Status = gBS->OpenProtocol (
+                  RootBridgeHandle,
+                  &gEfiPciRootBridgeIoProtocolGuid,
+                  (VOID **) &PciRootBridgeIo,
+                  gPciBusDriverBinding.DriverBindingHandle,
+                  RootBridgeHandle,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+
+  if (EFI_ERROR (Status)) {
+    return FALSE;
+  }
+
+  HostBridgeHandle = PciRootBridgeIo->ParentHandle;
+  for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
+    if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  Add host bridge handle to global variable for enumerating.
+
+  @param HostBridgeHandle   Host bridge handle.
+
+  @retval EFI_SUCCESS       Successfully added host bridge.
+  @retval EFI_ABORTED       Host bridge is NULL, or given host bridge
+                            has been in host bridge list.
+
+**/
+EFI_STATUS
+AddHostBridgeEnumerator (
+  IN EFI_HANDLE HostBridgeHandle
+  )
+{
+  UINTN Index;
+
+  if (HostBridgeHandle == NULL) {
+    return EFI_ABORTED;
+  }
+
+  for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
+    if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
+      return EFI_ABORTED;
+    }
+  }
+
+  if (Index < PCI_MAX_HOST_BRIDGE_NUM) {
+    gPciHostBrigeHandles[Index] = HostBridgeHandle;
+    gPciHostBridgeNumber++;
+  }
+
+  return EFI_SUCCESS;
+}
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.h
new file mode 100644
index 0000000000..2a34c9043c
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.h
@@ -0,0 +1,515 @@
+/** @file
+  PCI bus enumeration logic function declaration for PCI bus module.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_PCI_ENUMERATOR_H_
+#define _EFI_PCI_ENUMERATOR_H_
+
+#include "PciResourceSupport.h"
+
+/**
+  This routine is used to enumerate entire pci bus system
+  in a given platform.
+
+  @param Controller          Parent controller handle.
+  @param HostBridgeHandle    Host bridge handle.
+
+  @retval EFI_SUCCESS    PCI enumeration finished successfully.
+  @retval other          Some error occurred when enumerating the pci bus system.
+
+**/
+EFI_STATUS
+PciEnumerator (
+  IN EFI_HANDLE                    Controller,
+  IN EFI_HANDLE                    HostBridgeHandle
+  );
+
+/**
+  Enumerate PCI root bridge.
+
+  @param PciResAlloc   Pointer to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
+  @param RootBridgeDev Instance of root bridge device.
+
+  @retval EFI_SUCCESS  Successfully enumerated root bridge.
+  @retval other        Failed to enumerate root bridge.
+
+**/
+EFI_STATUS
+PciRootBridgeEnumerator (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc,
+  IN PCI_IO_DEVICE                                     *RootBridgeDev
+  );
+
+/**
+  This routine is used to process all PCI devices' Option Rom
+  on a certain root bridge.
+
+  @param Bridge     Given parent's root bridge.
+  @param RomBase    Base address of ROM driver loaded from.
+  @param MaxLength  Maximum rom size.
+
+**/
+VOID
+ProcessOptionRom (
+  IN PCI_IO_DEVICE *Bridge,
+  IN UINT64        RomBase,
+  IN UINT64        MaxLength
+  );
+
+/**
+  This routine is used to assign bus number to the given PCI bus system
+
+  @param Bridge             Parent root bridge instance.
+  @param StartBusNumber     Number of beginning.
+  @param SubBusNumber       The number of sub bus.
+
+  @retval EFI_SUCCESS       Successfully assigned bus number.
+  @retval EFI_DEVICE_ERROR  Failed to assign bus number.
+
+**/
+EFI_STATUS
+PciAssignBusNumber (
+  IN PCI_IO_DEVICE                      *Bridge,
+  IN UINT8                              StartBusNumber,
+  OUT UINT8                             *SubBusNumber
+  );
+
+/**
+  This routine is used to determine the root bridge attribute by interfacing
+  the host bridge resource allocation protocol.
+
+  @param PciResAlloc    Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+  @param RootBridgeDev  Root bridge instance
+
+  @retval EFI_SUCCESS  Successfully got root bridge's attribute.
+  @retval other        Failed to get attribute.
+
+**/
+EFI_STATUS
+DetermineRootBridgeAttributes (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
+  IN PCI_IO_DEVICE                                    *RootBridgeDev
+  );
+
+/**
+  Get Max Option Rom size on specified bridge.
+
+  @param Bridge    Given bridge device instance.
+
+  @return Max size of option rom needed.
+
+**/
+UINT32
+GetMaxOptionRomSize (
+  IN PCI_IO_DEVICE   *Bridge
+  );
+
+/**
+  Process attributes of devices on this host bridge
+
+  @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
+
+  @retval EFI_SUCCESS   Successfully process attribute.
+  @retval EFI_NOT_FOUND Can not find the specific root bridge device.
+  @retval other         Failed to determine the root bridge device's attribute.
+
+**/
+EFI_STATUS
+PciHostBridgeDeviceAttribute (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+  );
+
+/**
+  Get resource allocation status from the ACPI resource descriptor.
+
+  @param AcpiConfig       Point to Acpi configuration table.
+  @param IoResStatus      Return the status of I/O resource.
+  @param Mem32ResStatus   Return the status of 32-bit Memory resource.
+  @param PMem32ResStatus  Return the status of 32-bit Prefetchable Memory resource.
+  @param Mem64ResStatus   Return the status of 64-bit Memory resource.
+  @param PMem64ResStatus  Return the status of 64-bit Prefetchable Memory resource.
+
+**/
+VOID
+GetResourceAllocationStatus (
+  VOID        *AcpiConfig,
+  OUT UINT64  *IoResStatus,
+  OUT UINT64  *Mem32ResStatus,
+  OUT UINT64  *PMem32ResStatus,
+  OUT UINT64  *Mem64ResStatus,
+  OUT UINT64  *PMem64ResStatus
+  );
+
+/**
+  Remove a PCI device from device pool and mark its bar.
+
+  @param PciDevice Instance of Pci device.
+
+  @retval EFI_SUCCESS Successfully remove the PCI device.
+  @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge.
+
+**/
+EFI_STATUS
+RejectPciDevice (
+  IN PCI_IO_DEVICE       *PciDevice
+  );
+
+/**
+  Determine whethter a PCI device can be rejected.
+
+  @param  PciResNode Pointer to Pci resource node instance.
+
+  @retval TRUE  The PCI device can be rejected.
+  @retval TRUE  The PCI device cannot be rejected.
+
+**/
+BOOLEAN
+IsRejectiveDevice (
+  IN  PCI_RESOURCE_NODE   *PciResNode
+  );
+
+/**
+  Compare two resource nodes and get the larger resource consumer.
+
+  @param PciResNode1  resource node 1 want to be compared
+  @param PciResNode2  resource node 2 want to be compared
+
+  @return Larger resource node.
+
+**/
+PCI_RESOURCE_NODE *
+GetLargerConsumerDevice (
+  IN  PCI_RESOURCE_NODE   *PciResNode1,
+  IN  PCI_RESOURCE_NODE   *PciResNode2
+  );
+
+/**
+  Get the max resource consumer in the host resource pool.
+
+  @param ResPool  Pointer to resource pool node.
+
+  @return The max resource consumer in the host resource pool.
+
+**/
+PCI_RESOURCE_NODE *
+GetMaxResourceConsumerDevice (
+  IN  PCI_RESOURCE_NODE   *ResPool
+  );
+
+/**
+  Adjust host bridge allocation so as to reduce resource requirement
+
+  @param IoPool           Pointer to instance of I/O resource Node.
+  @param Mem32Pool        Pointer to instance of 32-bit memory resource Node.
+  @param PMem32Pool       Pointer to instance of 32-bit Prefetchable memory resource node.
+  @param Mem64Pool        Pointer to instance of 64-bit memory resource node.
+  @param PMem64Pool       Pointer to instance of 64-bit Prefetchable memory resource node.
+  @param IoResStatus      Status of I/O resource Node.
+  @param Mem32ResStatus   Status of 32-bit memory resource Node.
+  @param PMem32ResStatus  Status of 32-bit Prefetchable memory resource node.
+  @param Mem64ResStatus   Status of 64-bit memory resource node.
+  @param PMem64ResStatus  Status of 64-bit Prefetchable memory resource node.
+
+  @retval EFI_SUCCESS     Successfully adjusted resource on host bridge.
+  @retval EFI_ABORTED     Host bridge hasn't this resource type or no resource be adjusted.
+
+**/
+EFI_STATUS
+PciHostBridgeAdjustAllocation (
+  IN  PCI_RESOURCE_NODE   *IoPool,
+  IN  PCI_RESOURCE_NODE   *Mem32Pool,
+  IN  PCI_RESOURCE_NODE   *PMem32Pool,
+  IN  PCI_RESOURCE_NODE   *Mem64Pool,
+  IN  PCI_RESOURCE_NODE   *PMem64Pool,
+  IN  UINT64              IoResStatus,
+  IN  UINT64              Mem32ResStatus,
+  IN  UINT64              PMem32ResStatus,
+  IN  UINT64              Mem64ResStatus,
+  IN  UINT64              PMem64ResStatus
+  );
+
+/**
+  Summary requests for all resource type, and construct ACPI resource
+  requestor instance.
+
+  @param Bridge           detecting bridge
+  @param IoNode           Pointer to instance of I/O resource Node
+  @param Mem32Node        Pointer to instance of 32-bit memory resource Node
+  @param PMem32Node       Pointer to instance of 32-bit Pmemory resource node
+  @param Mem64Node        Pointer to instance of 64-bit memory resource node
+  @param PMem64Node       Pointer to instance of 64-bit Pmemory resource node
+  @param Config           Output buffer holding new constructed APCI resource requestor
+
+  @retval EFI_SUCCESS           Successfully constructed ACPI resource.
+  @retval EFI_OUT_OF_RESOURCES  No memory available.
+
+**/
+EFI_STATUS
+ConstructAcpiResourceRequestor (
+  IN PCI_IO_DEVICE      *Bridge,
+  IN PCI_RESOURCE_NODE  *IoNode,
+  IN PCI_RESOURCE_NODE  *Mem32Node,
+  IN PCI_RESOURCE_NODE  *PMem32Node,
+  IN PCI_RESOURCE_NODE  *Mem64Node,
+  IN PCI_RESOURCE_NODE  *PMem64Node,
+  OUT VOID              **Config
+  );
+
+/**
+  Get resource base from an acpi configuration descriptor.
+
+  @param Config       An acpi configuration descriptor.
+  @param IoBase       Output of I/O resource base address.
+  @param Mem32Base    Output of 32-bit memory base address.
+  @param PMem32Base   Output of 32-bit prefetchable memory base address.
+  @param Mem64Base    Output of 64-bit memory base address.
+  @param PMem64Base   Output of 64-bit prefetchable memory base address.
+
+**/
+VOID
+GetResourceBase (
+  IN VOID     *Config,
+  OUT UINT64  *IoBase,
+  OUT UINT64  *Mem32Base,
+  OUT UINT64  *PMem32Base,
+  OUT UINT64  *Mem64Base,
+  OUT UINT64  *PMem64Base
+  );
+
+/**
+  Enumerate pci bridge, allocate resource and determine attribute
+  for devices on this bridge.
+
+  @param BridgeDev    Pointer to instance of bridge device.
+
+  @retval EFI_SUCCESS Successfully enumerated PCI bridge.
+  @retval other       Failed to enumerate.
+
+**/
+EFI_STATUS
+PciBridgeEnumerator (
+  IN PCI_IO_DEVICE                                     *BridgeDev
+  );
+
+/**
+  Allocate all kinds of resource for PCI bridge.
+
+  @param  Bridge      Pointer to bridge instance.
+
+  @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.
+  @retval other       Failed to allocate resource for bridge.
+
+**/
+EFI_STATUS
+PciBridgeResourceAllocator (
+  IN PCI_IO_DEVICE  *Bridge
+  );
+
+/**
+  Get resource base address for a pci bridge device.
+
+  @param Bridge     Given Pci driver instance.
+  @param IoBase     Output for base address of I/O type resource.
+  @param Mem32Base  Output for base address of 32-bit memory type resource.
+  @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.
+  @param Mem64Base  Output for base address of 64-bit memory type resource.
+  @param PMem64Base Output for base address of 64-bit Pmemory type resource.
+
+  @retval EFI_SUCCESS           Successfully got resource base address.
+  @retval EFI_OUT_OF_RESOURCES  PCI bridge is not available.
+
+**/
+EFI_STATUS
+GetResourceBaseFromBridge (
+  IN  PCI_IO_DEVICE *Bridge,
+  OUT UINT64        *IoBase,
+  OUT UINT64        *Mem32Base,
+  OUT UINT64        *PMem32Base,
+  OUT UINT64        *Mem64Base,
+  OUT UINT64        *PMem64Base
+  );
+
+/**
+  Process Option Rom on this host bridge
+
+  @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
+
+  @retval EFI_NOT_FOUND Can not find the root bridge instance.
+  @retval EFI_SUCCESS   Success process.
+**/
+EFI_STATUS
+PciHostBridgeP2CProcess (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+  );
+
+/**
+   These are the notifications from the PCI bus driver that it is about to enter a certain
+   phase of the PCI enumeration process.
+
+   This member function can be used to notify the host bridge driver to perform specific actions,
+   including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
+   Eight notification points are defined at this time. See belows:
+   EfiPciHostBridgeBeginEnumeration       Resets the host bridge PCI apertures and internal data
+                                          structures. The PCI enumerator should issue this notification
+                                          before starting a fresh enumeration process. Enumeration cannot
+                                          be restarted after sending any other notification such as
+                                          EfiPciHostBridgeBeginBusAllocation.
+   EfiPciHostBridgeBeginBusAllocation     The bus allocation phase is about to begin. No specific action is
+                                          required here. This notification can be used to perform any
+                                          chipset-specific programming.
+   EfiPciHostBridgeEndBusAllocation       The bus allocation and bus programming phase is complete. No
+                                          specific action is required here. This notification can be used to
+                                          perform any chipset-specific programming.
+   EfiPciHostBridgeBeginResourceAllocation
+                                          The resource allocation phase is about to begin. No specific
+                                          action is required here. This notification can be used to perform
+                                          any chipset-specific programming.
+   EfiPciHostBridgeAllocateResources      Allocates resources per previously submitted requests for all the PCI
+                                          root bridges. These resource settings are returned on the next call to
+                                          GetProposedResources(). Before calling NotifyPhase() with a Phase of
+                                          EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
+                                          for gathering I/O and memory requests for
+                                          all the PCI root bridges and submitting these requests using
+                                          SubmitResources(). This function pads the resource amount
+                                          to suit the root bridge hardware, takes care of dependencies between
+                                          the PCI root bridges, and calls the Global Coherency Domain (GCD)
+                                          with the allocation request. In the case of padding, the allocated range
+                                          could be bigger than what was requested.
+   EfiPciHostBridgeSetResources           Programs the host bridge hardware to decode previously allocated
+                                          resources (proposed resources) for all the PCI root bridges. After the
+                                          hardware is programmed, reassigning resources will not be supported.
+                                          The bus settings are not affected.
+   EfiPciHostBridgeFreeResources          Deallocates resources that were previously allocated for all the PCI
+                                          root bridges and resets the I/O and memory apertures to their initial
+                                          state. The bus settings are not affected. If the request to allocate
+                                          resources fails, the PCI enumerator can use this notification to
+                                          deallocate previous resources, adjust the requests, and retry
+                                          allocation.
+   EfiPciHostBridgeEndResourceAllocation  The resource allocation phase is completed. No specific action is
+                                          required here. This notification can be used to perform any chipsetspecific
+                                          programming.
+
+   @param[in] PciResAlloc         The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+   @param[in] Phase               The phase during enumeration
+
+   @retval EFI_NOT_READY          This phase cannot be entered at this time. For example, this error
+                                  is valid for a Phase of EfiPciHostBridgeAllocateResources if
+                                  SubmitResources() has not been called for one or more
+                                  PCI root bridges before this call
+   @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error. This error is valid
+                                  for a Phase of EfiPciHostBridgeSetResources.
+   @retval EFI_INVALID_PARAMETER  Invalid phase parameter
+   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
+                                  This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
+                                  previously submitted resource requests cannot be fulfilled or
+                                  were only partially fulfilled.
+   @retval EFI_SUCCESS            The notification was accepted without any errors.
+
+**/
+EFI_STATUS
+NotifyPhase (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
+  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE       Phase
+  );
+
+/**
+  Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
+  stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
+  PCI controllers before enumeration.
+
+  This function is called during the PCI enumeration process. No specific action is expected from this
+  member function. It allows the host bridge driver to preinitialize individual PCI controllers before
+  enumeration.
+
+  @param Bridge            Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+  @param Bus               The bus number of the pci device.
+  @param Device            The device number of the pci device.
+  @param Func              The function number of the pci device.
+  @param Phase             The phase of the PCI device enumeration.
+
+  @retval EFI_SUCCESS              The requested parameters were returned.
+  @retval EFI_INVALID_PARAMETER    RootBridgeHandle is not a valid root bridge handle.
+  @retval EFI_INVALID_PARAMETER    Phase is not a valid phase that is defined in
+                                   EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
+  @retval EFI_DEVICE_ERROR         Programming failed due to a hardware error. The PCI enumerator should
+                                   not enumerate this device, including its child devices if it is a PCI-to-PCI
+                                   bridge.
+
+**/
+EFI_STATUS
+PreprocessController (
+  IN PCI_IO_DEVICE                                  *Bridge,
+  IN UINT8                                          Bus,
+  IN UINT8                                          Device,
+  IN UINT8                                          Func,
+  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE   Phase
+  );
+
+/**
+  This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has
+  happened on the hot-plug controller. Currently, the operations include add operation and remove operation..
+
+  @param This                 A pointer to the hot plug request protocol.
+  @param Operation            The operation the PCI bus driver is requested to make.
+  @param Controller           The handle of the hot-plug controller.
+  @param RemainingDevicePath  The remaining device path for the PCI-like hot-plug device.
+  @param NumberOfChildren     The number of child handles.
+                              For a add operation, it is an output parameter.
+                              For a remove operation, it's an input parameter.
+  @param ChildHandleBuffer    The buffer which contains the child handles.
+
+  @retval EFI_INVALID_PARAMETER  Operation is not a legal value.
+                                 Controller is NULL or not a valid handle.
+                                 NumberOfChildren is NULL.
+                                 ChildHandleBuffer is NULL while Operation is add.
+  @retval EFI_OUT_OF_RESOURCES   There are no enough resources to start the devices.
+  @retval EFI_NOT_FOUND          Can not find bridge according to controller handle.
+  @retval EFI_SUCCESS            The handles for the specified device have been created or destroyed
+                                 as requested, and for an add operation, the new handles are
+                                 returned in ChildHandleBuffer.
+**/
+EFI_STATUS
+EFIAPI
+PciHotPlugRequestNotify (
+  IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,
+  IN EFI_PCI_HOTPLUG_OPERATION        Operation,
+  IN EFI_HANDLE                       Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL         * RemainingDevicePath OPTIONAL,
+  IN OUT UINT8                        *NumberOfChildren,
+  IN OUT EFI_HANDLE                   * ChildHandleBuffer
+  );
+
+/**
+  Search hostbridge according to given handle
+
+  @param RootBridgeHandle  Host bridge handle.
+
+  @retval TRUE             Found host bridge handle.
+  @retval FALSE            Not found hot bridge handle.
+
+**/
+BOOLEAN
+SearchHostBridgeHandle (
+  IN EFI_HANDLE RootBridgeHandle
+  );
+
+/**
+  Add host bridge handle to global variable for enumerating.
+
+  @param HostBridgeHandle   Host bridge handle.
+
+  @retval EFI_SUCCESS       Successfully added host bridge.
+  @retval EFI_ABORTED       Host bridge is NULL, or given host bridge
+                            has been in host bridge list.
+
+**/
+EFI_STATUS
+AddHostBridgeEnumerator (
+  IN EFI_HANDLE HostBridgeHandle
+  );
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
new file mode 100644
index 0000000000..99b04a462b
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
@@ -0,0 +1,2885 @@
+/** @file
+  PCI emumeration support functions implementation for PCI Bus module.
+
+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+Copyright (c) 2021, American Megatrends International LLC.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+
+extern CHAR16  *mBarTypeStr[];
+extern EDKII_DEVICE_SECURITY_PROTOCOL                          *mDeviceSecurityProtocol;
+
+#define OLD_ALIGN   0xFFFFFFFFFFFFFFFFULL
+#define EVEN_ALIGN  0xFFFFFFFFFFFFFFFEULL
+#define SQUAD_ALIGN 0xFFFFFFFFFFFFFFFDULL
+#define DQUAD_ALIGN 0xFFFFFFFFFFFFFFFCULL
+
+/**
+  This routine is used to check whether the pci device is present.
+
+  @param PciRootBridgeIo   Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param Pci               Output buffer for PCI device configuration space.
+  @param Bus               PCI bus NO.
+  @param Device            PCI device NO.
+  @param Func              PCI Func NO.
+
+  @retval EFI_NOT_FOUND    PCI device not present.
+  @retval EFI_SUCCESS      PCI device is found.
+
+**/
+EFI_STATUS
+PciDevicePresent (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL     *PciRootBridgeIo,
+  OUT PCI_TYPE00                          *Pci,
+  IN  UINT8                               Bus,
+  IN  UINT8                               Device,
+  IN  UINT8                               Func
+  )
+{
+  UINT64      Address;
+  EFI_STATUS  Status;
+
+  //
+  // Create PCI address map in terms of Bus, Device and Func
+  //
+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+
+
+//TiogaPass Override START : Skip SPI controller from Enumeration
+
+//
+//
+// It is necessary to skip SPI controller from Enumeration process otherwise SPI access runing DXE/DXE SMM
+// will causes failures writting to SPI. This is a WA for LBG since currently OS hidde is not working.
+//
+  if(( Bus == 0x0) && ( Device == 0x1F) && (Func == 0x05)){
+    DEBUG ((EFI_D_INFO, "DEBUG - Address - 0x%x  BUS %x DEV %x Func %x SKIP\n", Address, Bus, Device, Func));
+    return EFI_NOT_FOUND;
+  }
+
+//TiogaPass Override END
+
+  //
+  // Read the Vendor ID register
+  //
+  Status = PciRootBridgeIo->Pci.Read (
+                                  PciRootBridgeIo,
+                                  EfiPciWidthUint32,
+                                  Address,
+                                  1,
+                                  Pci
+                                  );
+
+  if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {
+    //
+    // Read the entire config header for the device
+    //
+    Status = PciRootBridgeIo->Pci.Read (
+                                    PciRootBridgeIo,
+                                    EfiPciWidthUint32,
+                                    Address,
+                                    sizeof (PCI_TYPE00) / sizeof (UINT32),
+                                    Pci
+                                    );
+
+    return EFI_SUCCESS;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Collect all the resource information under this root bridge.
+
+  A database that records all the information about pci device subject to this
+  root bridge will then be created.
+
+  @param Bridge         Parent bridge instance.
+  @param StartBusNumber Bus number of beginning.
+
+  @retval EFI_SUCCESS   PCI device is found.
+  @retval other         Some error occurred when reading PCI bridge information.
+
+**/
+EFI_STATUS
+PciPciDeviceInfoCollector (
+  IN PCI_IO_DEVICE                      *Bridge,
+  IN UINT8                              StartBusNumber
+  )
+{
+  EFI_STATUS          Status;
+  PCI_TYPE00          Pci;
+  UINT8               Device;
+  UINT8               Func;
+  UINT8               SecBus;
+  PCI_IO_DEVICE       *PciIoDevice;
+  EFI_PCI_IO_PROTOCOL *PciIo;
+
+  Status  = EFI_SUCCESS;
+  SecBus  = 0;
+
+  for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+
+    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+
+      //
+      // Check to see whether PCI device is present
+      //
+      Status = PciDevicePresent (
+                 Bridge->PciRootBridgeIo,
+                 &Pci,
+                 (UINT8) StartBusNumber,
+                 (UINT8) Device,
+                 (UINT8) Func
+                 );
+
+      if (EFI_ERROR (Status) && Func == 0) {
+        //
+        // go to next device if there is no Function 0
+        //
+        break;
+      }
+
+      if (!EFI_ERROR (Status)) {
+
+        //
+        // Call back to host bridge function
+        //
+        PreprocessController (Bridge, (UINT8) StartBusNumber, Device, Func, EfiPciBeforeResourceCollection);
+
+        //
+        // Collect all the information about the PCI device discovered
+        //
+        Status = PciSearchDevice (
+                   Bridge,
+                   &Pci,
+                   (UINT8) StartBusNumber,
+                   Device,
+                   Func,
+                   &PciIoDevice
+                   );
+
+        //
+        // Recursively scan PCI busses on the other side of PCI-PCI bridges
+        //
+        //
+        if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
+
+          //
+          // If it is PPB, we need to get the secondary bus to continue the enumeration
+          //
+          PciIo   = &(PciIoDevice->PciIo);
+
+          Status  = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, 1, &SecBus);
+
+          if (EFI_ERROR (Status)) {
+            return Status;
+          }
+
+          //
+          // Ensure secondary bus number is greater than the primary bus number to avoid
+          // any potential dead loop when PcdPciDisableBusEnumeration is set to TRUE
+          //
+          if (SecBus <= StartBusNumber) {
+            break;
+          }
+
+          //
+          // Get resource padding for PPB
+          //
+          GetResourcePaddingPpb (PciIoDevice);
+
+          //
+          // Deep enumerate the next level bus
+          //
+          Status = PciPciDeviceInfoCollector (
+                     PciIoDevice,
+                     (UINT8) (SecBus)
+                     );
+
+        }
+
+        if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
+
+          //
+          // Skip sub functions, this is not a multi function device
+          //
+          Func = PCI_MAX_FUNC;
+        }
+      }
+
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Search required device and create PCI device instance.
+
+  @param Bridge     Parent bridge instance.
+  @param Pci        Input PCI device information block.
+  @param Bus        PCI bus NO.
+  @param Device     PCI device NO.
+  @param Func       PCI func  NO.
+  @param PciDevice  Output of searched PCI device instance.
+
+  @retval EFI_SUCCESS           Successfully created PCI device instance.
+  @retval EFI_OUT_OF_RESOURCES  Cannot get PCI device information.
+
+**/
+EFI_STATUS
+PciSearchDevice (
+  IN  PCI_IO_DEVICE                         *Bridge,
+  IN  PCI_TYPE00                            *Pci,
+  IN  UINT8                                 Bus,
+  IN  UINT8                                 Device,
+  IN  UINT8                                 Func,
+  OUT PCI_IO_DEVICE                         **PciDevice
+  )
+{
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = NULL;
+
+  DEBUG ((
+    EFI_D_INFO,
+    "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",
+    IS_PCI_BRIDGE (Pci) ?     L"PPB" :
+    IS_CARDBUS_BRIDGE (Pci) ? L"P2C" :
+                              L"PCI",
+    Bus, Device, Func
+    ));
+
+  if (!IS_PCI_BRIDGE (Pci)) {
+
+    if (IS_CARDBUS_BRIDGE (Pci)) {
+      PciIoDevice = GatherP2CInfo (
+                      Bridge,
+                      Pci,
+                      Bus,
+                      Device,
+                      Func
+                      );
+      if ((PciIoDevice != NULL) && gFullEnumeration) {
+        InitializeP2C (PciIoDevice);
+      }
+    } else {
+
+      //
+      // Create private data for Pci Device
+      //
+      PciIoDevice = GatherDeviceInfo (
+                      Bridge,
+                      Pci,
+                      Bus,
+                      Device,
+                      Func
+                      );
+
+    }
+
+  } else {
+
+    //
+    // Create private data for PPB
+    //
+    PciIoDevice = GatherPpbInfo (
+                    Bridge,
+                    Pci,
+                    Bus,
+                    Device,
+                    Func
+                    );
+
+    //
+    // Special initialization for PPB including making the PPB quiet
+    //
+    if ((PciIoDevice != NULL) && gFullEnumeration) {
+      InitializePpb (PciIoDevice);
+    }
+  }
+
+  if (PciIoDevice == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Update the bar information for this PCI device so as to support some specific device
+  //
+  UpdatePciInfo (PciIoDevice);
+
+  if (PciIoDevice->DevicePath == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Detect this function has option rom
+  //
+  if (gFullEnumeration) {
+
+    if (!IS_CARDBUS_BRIDGE (Pci)) {
+
+      GetOpRomInfo (PciIoDevice);
+
+    }
+
+    ResetPowerManagementFeature (PciIoDevice);
+
+  }
+
+  //
+  // Insert it into a global tree for future reference
+  //
+  InsertPciDevice (Bridge, PciIoDevice);
+
+  //
+  // Determine PCI device attributes
+  //
+
+  if (PciDevice != NULL) {
+    *PciDevice = PciIoDevice;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Dump the PPB padding resource information.
+
+  @param PciIoDevice     PCI IO instance.
+  @param ResourceType    The desired resource type to dump.
+                         PciBarTypeUnknown means to dump all types of resources.
+**/
+VOID
+DumpPpbPaddingResource (
+  IN PCI_IO_DEVICE                    *PciIoDevice,
+  IN PCI_BAR_TYPE                     ResourceType
+  )
+{
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
+  PCI_BAR_TYPE                      Type;
+
+  if (PciIoDevice->ResourcePaddingDescriptors == NULL) {
+    return;
+  }
+
+  if (ResourceType == PciBarTypeIo16 || ResourceType == PciBarTypeIo32) {
+    ResourceType = PciBarTypeIo;
+  }
+
+  for (Descriptor = PciIoDevice->ResourcePaddingDescriptors; Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR; Descriptor++) {
+
+    Type = PciBarTypeUnknown;
+    if (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {
+      Type = PciBarTypeIo;
+    } else if (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
+
+      if (Descriptor->AddrSpaceGranularity == 32) {
+        //
+        // prefetchable
+        //
+        if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) {
+          Type = PciBarTypePMem32;
+        }
+
+        //
+        // Non-prefetchable
+        //
+        if (Descriptor->SpecificFlag == 0) {
+          Type = PciBarTypeMem32;
+        }
+      }
+
+      if (Descriptor->AddrSpaceGranularity == 64) {
+        //
+        // prefetchable
+        //
+        if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) {
+          Type = PciBarTypePMem64;
+        }
+
+        //
+        // Non-prefetchable
+        //
+        if (Descriptor->SpecificFlag == 0) {
+          Type = PciBarTypeMem64;
+        }
+      }
+    }
+
+    if ((Type != PciBarTypeUnknown) && ((ResourceType == PciBarTypeUnknown) || (ResourceType == Type))) {
+      DEBUG ((
+        EFI_D_INFO,
+        "   Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",
+        mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor->AddrLen
+        ));
+    }
+  }
+
+}
+
+/**
+  Dump the PCI BAR information.
+
+  @param PciIoDevice     PCI IO instance.
+**/
+VOID
+DumpPciBars (
+  IN PCI_IO_DEVICE                    *PciIoDevice
+  )
+{
+  UINTN                               Index;
+
+  for (Index = 0; Index < PCI_MAX_BAR; Index++) {
+    if (PciIoDevice->PciBar[Index].BarType == PciBarTypeUnknown) {
+      continue;
+    }
+
+    DEBUG ((
+      EFI_D_INFO,
+      "   BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
+      Index, mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType, PciBarTypeMaxType)],
+      PciIoDevice->PciBar[Index].Alignment, PciIoDevice->PciBar[Index].Length, PciIoDevice->PciBar[Index].Offset
+      ));
+  }
+
+  for (Index = 0; Index < PCI_MAX_BAR; Index++) {
+    if ((PciIoDevice->VfPciBar[Index].BarType == PciBarTypeUnknown) && (PciIoDevice->VfPciBar[Index].Length == 0)) {
+      continue;
+    }
+
+    DEBUG ((
+      EFI_D_INFO,
+      " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
+      Index, mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType, PciBarTypeMaxType)],
+      PciIoDevice->VfPciBar[Index].Alignment, PciIoDevice->VfPciBar[Index].Length, PciIoDevice->VfPciBar[Index].Offset
+      ));
+  }
+  DEBUG ((EFI_D_INFO, "\n"));
+}
+
+/**
+  Create PCI device instance for PCI device.
+
+  @param Bridge   Parent bridge instance.
+  @param Pci      Input PCI device information block.
+  @param Bus      PCI device Bus NO.
+  @param Device   PCI device Device NO.
+  @param Func     PCI device's func NO.
+
+  @return  Created PCI device instance.
+
+**/
+PCI_IO_DEVICE *
+GatherDeviceInfo (
+  IN PCI_IO_DEVICE                    *Bridge,
+  IN PCI_TYPE00                       *Pci,
+  IN UINT8                            Bus,
+  IN UINT8                            Device,
+  IN UINT8                            Func
+  )
+{
+  UINTN                           Offset;
+  UINTN                           BarIndex;
+  PCI_IO_DEVICE                   *PciIoDevice;
+
+  PciIoDevice = CreatePciIoDevice (
+                  Bridge,
+                  Pci,
+                  Bus,
+                  Device,
+                  Func
+                  );
+
+  if (PciIoDevice == NULL) {
+    return NULL;
+  }
+
+  //
+  // If it is a full enumeration, disconnect the device in advance
+  //
+  if (gFullEnumeration) {
+
+    PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
+
+  }
+
+  //
+  // Start to parse the bars
+  //
+  for (Offset = 0x10, BarIndex = 0; Offset <= 0x24 && BarIndex < PCI_MAX_BAR; BarIndex++) {
+    Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
+  }
+
+  //
+  // Parse the SR-IOV VF bars
+  //
+  if (PcdGetBool (PcdSrIovSupport) && PciIoDevice->SrIovCapabilityOffset != 0) {
+    for (Offset = PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0, BarIndex = 0;
+         Offset <= PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5;
+         BarIndex++) {
+
+      ASSERT (BarIndex < PCI_MAX_BAR);
+      Offset = PciIovParseVfBar (PciIoDevice, Offset, BarIndex);
+    }
+  }
+
+  DEBUG_CODE (DumpPciBars (PciIoDevice););
+  return PciIoDevice;
+}
+
+/**
+  Create PCI device instance for PCI-PCI bridge.
+
+  @param Bridge   Parent bridge instance.
+  @param Pci      Input PCI device information block.
+  @param Bus      PCI device Bus NO.
+  @param Device   PCI device Device NO.
+  @param Func     PCI device's func NO.
+
+  @return  Created PCI device instance.
+
+**/
+PCI_IO_DEVICE *
+GatherPpbInfo (
+  IN PCI_IO_DEVICE                    *Bridge,
+  IN PCI_TYPE00                       *Pci,
+  IN UINT8                            Bus,
+  IN UINT8                            Device,
+  IN UINT8                            Func
+  )
+{
+  PCI_IO_DEVICE                   *PciIoDevice;
+  EFI_STATUS                      Status;
+  UINT8                           Value;
+  EFI_PCI_IO_PROTOCOL             *PciIo;
+  UINT8                           Temp;
+  UINT32                          PMemBaseLimit;
+  UINT16                          PrefetchableMemoryBase;
+  UINT16                          PrefetchableMemoryLimit;
+
+  PciIoDevice = CreatePciIoDevice (
+                  Bridge,
+                  Pci,
+                  Bus,
+                  Device,
+                  Func
+                  );
+
+  if (PciIoDevice == NULL) {
+    return NULL;
+  }
+
+  if (gFullEnumeration) {
+    PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
+
+    //
+    // Initialize the bridge control register
+    //
+    PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);
+
+  }
+
+  //
+  // PPB can have two BARs
+  //
+  if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) == 0x14) {
+    //
+    // Not 64-bit bar
+    //
+    PciParseBar (PciIoDevice, 0x14, PPB_BAR_1);
+  }
+
+  PciIo = &PciIoDevice->PciIo;
+
+  //
+  // Test whether it support 32 decode or not
+  //
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
+
+  if (Value != 0) {
+    if ((Value & 0x01) != 0) {
+      PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;
+    } else {
+      PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
+    }
+  }
+
+  //
+  // if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes
+  // PCI bridge supporting non-standard I/O window alignment less than 4K.
+  //
+
+  PciIoDevice->BridgeIoAlignment = 0xFFF;
+  if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe)) {
+    //
+    // Check any bits of bit 3-1 of I/O Base Register are writable.
+    // if so, it is assumed non-standard I/O window alignment is supported by this bridge.
+    // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its content can't be assumed.
+    //
+    Value = (UINT8)(Temp ^ (BIT3 | BIT2 | BIT1));
+    PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
+    PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
+    PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
+    Value = (UINT8)((Value ^ Temp) & (BIT3 | BIT2 | BIT1));
+    switch (Value) {
+      case BIT3:
+        PciIoDevice->BridgeIoAlignment = 0x7FF;
+        break;
+      case BIT3 | BIT2:
+        PciIoDevice->BridgeIoAlignment = 0x3FF;
+        break;
+      case BIT3 | BIT2 | BIT1:
+        PciIoDevice->BridgeIoAlignment = 0x1FF;
+        break;
+    }
+  }
+
+  Status = BarExisted (
+            PciIoDevice,
+            0x24,
+            NULL,
+            &PMemBaseLimit
+            );
+
+  //
+  // Test if it supports 64 memory or not
+  //
+  // The bottom 4 bits of both the Prefetchable Memory Base and Prefetchable Memory Limit
+  // registers:
+  //   0 - the bridge supports only 32 bit addresses.
+  //   1 - the bridge supports 64-bit addresses.
+  //
+  PrefetchableMemoryBase = (UINT16)(PMemBaseLimit & 0xffff);
+  PrefetchableMemoryLimit = (UINT16)(PMemBaseLimit >> 16);
+  if (!EFI_ERROR (Status) &&
+      (PrefetchableMemoryBase & 0x000f) == 0x0001 &&
+      (PrefetchableMemoryLimit & 0x000f) == 0x0001) {
+    Status = BarExisted (
+              PciIoDevice,
+              0x28,
+              NULL,
+              NULL
+              );
+
+    if (!EFI_ERROR (Status)) {
+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
+    } else {
+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
+    }
+  }
+
+  //
+  // Memory 32 code is required for ppb
+  //
+  PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
+
+  GetResourcePaddingPpb (PciIoDevice);
+
+  DEBUG_CODE (
+    DumpPpbPaddingResource (PciIoDevice, PciBarTypeUnknown);
+    DumpPciBars (PciIoDevice);
+  );
+
+  return PciIoDevice;
+}
+
+
+/**
+  Create PCI device instance for PCI Card bridge device.
+
+  @param Bridge   Parent bridge instance.
+  @param Pci      Input PCI device information block.
+  @param Bus      PCI device Bus NO.
+  @param Device   PCI device Device NO.
+  @param Func     PCI device's func NO.
+
+  @return  Created PCI device instance.
+
+**/
+PCI_IO_DEVICE *
+GatherP2CInfo (
+  IN PCI_IO_DEVICE                    *Bridge,
+  IN PCI_TYPE00                       *Pci,
+  IN UINT8                            Bus,
+  IN UINT8                            Device,
+  IN UINT8                            Func
+  )
+{
+  PCI_IO_DEVICE                   *PciIoDevice;
+
+  PciIoDevice = CreatePciIoDevice (
+                  Bridge,
+                  Pci,
+                  Bus,
+                  Device,
+                  Func
+                  );
+
+  if (PciIoDevice == NULL) {
+    return NULL;
+  }
+
+  if (gFullEnumeration) {
+    PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
+
+    //
+    // Initialize the bridge control register
+    //
+    PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);
+  }
+
+  //
+  // P2C only has one bar that is in 0x10
+  //
+  PciParseBar (PciIoDevice, 0x10, P2C_BAR_0);
+
+  //
+  // Read PciBar information from the bar register
+  //
+  GetBackPcCardBar (PciIoDevice);
+  PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED  |
+                         EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |
+                         EFI_BRIDGE_IO32_DECODE_SUPPORTED;
+
+  DEBUG_CODE (DumpPciBars (PciIoDevice););
+
+  return PciIoDevice;
+}
+
+/**
+  Create device path for pci device.
+
+  @param ParentDevicePath  Parent bridge's path.
+  @param PciIoDevice       Pci device instance.
+
+  @return Device path protocol instance for specific pci device.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+CreatePciDevicePath (
+  IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+  IN  PCI_IO_DEVICE            *PciIoDevice
+  )
+{
+
+  PCI_DEVICE_PATH PciNode;
+
+  //
+  // Create PCI device path
+  //
+  PciNode.Header.Type     = HARDWARE_DEVICE_PATH;
+  PciNode.Header.SubType  = HW_PCI_DP;
+  SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
+
+  PciNode.Device          = PciIoDevice->DeviceNumber;
+  PciNode.Function        = PciIoDevice->FunctionNumber;
+  PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);
+
+  return PciIoDevice->DevicePath;
+}
+
+/**
+  Check whether the PCI IOV VF bar is existed or not.
+
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.
+  @param Offset            The offset.
+  @param BarLengthValue    The bar length value returned.
+  @param OriginalBarValue  The original bar value returned.
+
+  @retval EFI_NOT_FOUND    The bar doesn't exist.
+  @retval EFI_SUCCESS      The bar exist.
+
+**/
+EFI_STATUS
+VfBarExisted (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  IN UINTN         Offset,
+  OUT UINT32       *BarLengthValue,
+  OUT UINT32       *OriginalBarValue
+  )
+{
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  UINT32              OriginalValue;
+  UINT32              Value;
+  EFI_TPL             OldTpl;
+
+  //
+  // Ensure it is called properly
+  //
+  ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);
+  if (PciIoDevice->SrIovCapabilityOffset == 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  PciIo = &PciIoDevice->PciIo;
+
+  //
+  // Preserve the original value
+  //
+
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);
+
+  //
+  // Raise TPL to high level to disable timer interrupt while the BAR is probed
+  //
+  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &gAllOne);
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &Value);
+
+  //
+  // Write back the original value
+  //
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);
+
+  //
+  // Restore TPL to its original level
+  //
+  gBS->RestoreTPL (OldTpl);
+
+  if (BarLengthValue != NULL) {
+    *BarLengthValue = Value;
+  }
+
+  if (OriginalBarValue != NULL) {
+    *OriginalBarValue = OriginalValue;
+  }
+
+  if (Value == 0) {
+    return EFI_NOT_FOUND;
+  } else {
+    return EFI_SUCCESS;
+  }
+}
+
+/**
+  Check whether the bar is existed or not.
+
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.
+  @param Offset            The offset.
+  @param BarLengthValue    The bar length value returned.
+  @param OriginalBarValue  The original bar value returned.
+
+  @retval EFI_NOT_FOUND    The bar doesn't exist.
+  @retval EFI_SUCCESS      The bar exist.
+
+**/
+EFI_STATUS
+BarExisted (
+  IN  PCI_IO_DEVICE *PciIoDevice,
+  IN  UINTN         Offset,
+  OUT UINT32        *BarLengthValue,
+  OUT UINT32        *OriginalBarValue
+  )
+{
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  UINT32              OriginalValue;
+  UINT32              Value;
+  EFI_TPL             OldTpl;
+
+  PciIo = &PciIoDevice->PciIo;
+
+  //
+  // Preserve the original value
+  //
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
+
+  //
+  // Raise TPL to high level to disable timer interrupt while the BAR is probed
+  //
+  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);
+
+  //
+  // Write back the original value
+  //
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
+
+  //
+  // Restore TPL to its original level
+  //
+  gBS->RestoreTPL (OldTpl);
+
+  if (BarLengthValue != NULL) {
+    *BarLengthValue = Value;
+  }
+
+  if (OriginalBarValue != NULL) {
+    *OriginalBarValue = OriginalValue;
+  }
+
+  if (Value == 0) {
+    return EFI_NOT_FOUND;
+  } else {
+    return EFI_SUCCESS;
+  }
+}
+
+/**
+  Test whether the device can support given attributes.
+
+  @param PciIoDevice      Pci device instance.
+  @param Command          Input command register value, and
+                          returned supported register value.
+  @param BridgeControl    Input bridge control value for PPB or P2C, and
+                          returned supported bridge control value.
+  @param OldCommand       Returned and stored old command register offset.
+  @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.
+
+**/
+VOID
+PciTestSupportedAttribute (
+  IN     PCI_IO_DEVICE                      *PciIoDevice,
+  IN OUT UINT16                             *Command,
+  IN OUT UINT16                             *BridgeControl,
+     OUT UINT16                             *OldCommand,
+     OUT UINT16                             *OldBridgeControl
+  )
+{
+  EFI_TPL OldTpl;
+
+  //
+  // Preserve the original value
+  //
+  PCI_READ_COMMAND_REGISTER (PciIoDevice, OldCommand);
+
+  //
+  // Raise TPL to high level to disable timer interrupt while the BAR is probed
+  //
+  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+  PCI_SET_COMMAND_REGISTER (PciIoDevice, *Command);
+  PCI_READ_COMMAND_REGISTER (PciIoDevice, Command);
+
+  //
+  // Write back the original value
+  //
+  PCI_SET_COMMAND_REGISTER (PciIoDevice, *OldCommand);
+
+  //
+  // Restore TPL to its original level
+  //
+  gBS->RestoreTPL (OldTpl);
+
+  if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+
+    //
+    // Preserve the original value
+    //
+    PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, OldBridgeControl);
+
+    //
+    // Raise TPL to high level to disable timer interrupt while the BAR is probed
+    //
+    OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+    PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *BridgeControl);
+    PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);
+
+    //
+    // Write back the original value
+    //
+    PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *OldBridgeControl);
+
+    //
+    // Restore TPL to its original level
+    //
+    gBS->RestoreTPL (OldTpl);
+
+  } else {
+    *OldBridgeControl = 0;
+    *BridgeControl    = 0;
+  }
+}
+
+/**
+  Set the supported or current attributes of a PCI device.
+
+  @param PciIoDevice    Structure pointer for PCI device.
+  @param Command        Command register value.
+  @param BridgeControl  Bridge control value for PPB or P2C.
+  @param Option         Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
+
+**/
+VOID
+PciSetDeviceAttribute (
+  IN PCI_IO_DEVICE                      *PciIoDevice,
+  IN UINT16                             Command,
+  IN UINT16                             BridgeControl,
+  IN UINTN                              Option
+  )
+{
+  UINT64  Attributes;
+
+  Attributes = 0;
+
+  if ((Command & EFI_PCI_COMMAND_IO_SPACE) != 0) {
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;
+  }
+
+  if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) != 0) {
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;
+  }
+
+  if ((Command & EFI_PCI_COMMAND_BUS_MASTER) != 0) {
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
+  }
+
+  if ((Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
+  }
+
+  if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) {
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
+  }
+
+  if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) != 0) {
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
+  }
+
+  if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16) != 0) {
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16;
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16;
+  }
+
+  if (Option == EFI_SET_SUPPORTS) {
+
+    Attributes |= (UINT64) (EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |
+                  EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED        |
+                  EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE       |
+                  EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE      |
+                  EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM         |
+                  EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE);
+
+    if (IS_PCI_LPC (&PciIoDevice->Pci)) {
+        Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;
+        Attributes |= (mReserveIsaAliases ? (UINT64) EFI_PCI_IO_ATTRIBUTE_ISA_IO : \
+                                            (UINT64) EFI_PCI_IO_ATTRIBUTE_ISA_IO_16);
+    }
+
+    if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+      //
+      // For bridge, it should support IDE attributes
+      //
+      Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
+      Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
+
+      if (mReserveVgaAliases) {
+        Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 | \
+                                EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16);
+      } else {
+        Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO | \
+                                EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);
+      }
+    } else {
+
+      if (IS_PCI_IDE (&PciIoDevice->Pci)) {
+        Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
+        Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
+      }
+
+      if (IS_PCI_VGA (&PciIoDevice->Pci)) {
+        Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
+        Attributes |= (mReserveVgaAliases ? (UINT64) EFI_PCI_IO_ATTRIBUTE_VGA_IO : \
+                                            (UINT64) EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);
+      }
+    }
+
+    PciIoDevice->Supports = Attributes;
+    PciIoDevice->Supports &= ( (PciIoDevice->Parent->Supports) | \
+                               EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | \
+                               EFI_PCI_IO_ATTRIBUTE_BUS_MASTER );
+
+  } else {
+    //
+    // When this attribute is clear, the RomImage and RomSize fields in the PCI IO were
+    // initialized based on the PCI option ROM found through the ROM BAR of the PCI controller.
+    // When this attribute is set, the PCI option ROM described by the RomImage and RomSize
+    // fields is not from the the ROM BAR of the PCI controller.
+    //
+    if (!PciIoDevice->EmbeddedRom) {
+      Attributes |= EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM;
+    }
+    PciIoDevice->Attributes = Attributes;
+  }
+}
+
+/**
+  Determine if the device can support Fast Back to Back attribute.
+
+  @param PciIoDevice  Pci device instance.
+  @param StatusIndex  Status register value.
+
+  @retval EFI_SUCCESS       This device support Fast Back to Back attribute.
+  @retval EFI_UNSUPPORTED   This device doesn't support Fast Back to Back attribute.
+
+**/
+EFI_STATUS
+GetFastBackToBackSupport (
+  IN PCI_IO_DEVICE                      *PciIoDevice,
+  IN UINT8                              StatusIndex
+  )
+{
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  EFI_STATUS          Status;
+  UINT32              StatusRegister;
+
+  //
+  // Read the status register
+  //
+  PciIo   = &PciIoDevice->PciIo;
+  Status  = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, StatusIndex, 1, &StatusRegister);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Check the Fast B2B bit
+  //
+  if ((StatusRegister & EFI_PCI_FAST_BACK_TO_BACK_CAPABLE) != 0) {
+    return EFI_SUCCESS;
+  } else {
+    return EFI_UNSUPPORTED;
+  }
+}
+
+/**
+  Process the option ROM for all the children of the specified parent PCI device.
+  It can only be used after the first full Option ROM process.
+
+  @param PciIoDevice Pci device instance.
+
+**/
+VOID
+ProcessOptionRomLight (
+  IN PCI_IO_DEVICE                      *PciIoDevice
+  )
+{
+  PCI_IO_DEVICE   *Temp;
+  LIST_ENTRY      *CurrentLink;
+
+  //
+  // For RootBridge, PPB , P2C, go recursively to traverse all its children
+  //
+  CurrentLink = PciIoDevice->ChildList.ForwardLink;
+  while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
+
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    if (!IsListEmpty (&Temp->ChildList)) {
+      ProcessOptionRomLight (Temp);
+    }
+
+    Temp->AllOpRomProcessed = PciRomGetImageMapping (Temp);
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+}
+
+/**
+  Determine the related attributes of all devices under a Root Bridge.
+
+  @param PciIoDevice   PCI device instance.
+
+**/
+EFI_STATUS
+DetermineDeviceAttribute (
+  IN PCI_IO_DEVICE                      *PciIoDevice
+  )
+{
+  UINT16          Command;
+  UINT16          BridgeControl;
+  UINT16          OldCommand;
+  UINT16          OldBridgeControl;
+  BOOLEAN         FastB2BSupport;
+  PCI_IO_DEVICE   *Temp;
+  LIST_ENTRY      *CurrentLink;
+  EFI_STATUS      Status;
+
+  //
+  // For Root Bridge, just copy it by RootBridgeIo protocol
+  // so as to keep consistent with the actual attribute
+  //
+  if (PciIoDevice->Parent == NULL) {
+    Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
+                                            PciIoDevice->PciRootBridgeIo,
+                                            &PciIoDevice->Supports,
+                                            &PciIoDevice->Attributes
+                                            );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    //
+    // Assume the PCI Root Bridge supports DAC
+    //
+    PciIoDevice->Supports |= (UINT64)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |
+                              EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |
+                              EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE);
+
+  } else {
+
+    //
+    // Set the attributes to be checked for common PCI devices and PPB or P2C
+    // Since some devices only support part of them, it is better to set the
+    // attribute according to its command or bridge control register
+    //
+    Command = EFI_PCI_COMMAND_IO_SPACE     |
+              EFI_PCI_COMMAND_MEMORY_SPACE |
+              EFI_PCI_COMMAND_BUS_MASTER   |
+              EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
+
+    BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16;
+
+    //
+    // Test whether the device can support attributes above
+    //
+    PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl);
+
+    //
+    // Set the supported attributes for specified PCI device
+    //
+    PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS);
+
+    //
+    // Set the current attributes for specified PCI device
+    //
+    PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);
+
+    //
+    // Enable other PCI supported attributes but not defined in PCI_IO_PROTOCOL
+    // For PCI Express devices, Memory Write and Invalidate is hardwired to 0b so only enable it for PCI devices.
+    if (!PciIoDevice->IsPciExp) {
+      PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);
+    }
+  }
+
+  FastB2BSupport = TRUE;
+
+  //
+  // P2C can not support FB2B on the secondary side
+  //
+  if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+    FastB2BSupport = FALSE;
+  }
+
+  //
+  // For RootBridge, PPB , P2C, go recursively to traverse all its children
+  //
+  CurrentLink = PciIoDevice->ChildList.ForwardLink;
+  while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
+
+    Temp    = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+    Status  = DetermineDeviceAttribute (Temp);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    //
+    // Detect Fast Back to Back support for the device under the bridge
+    //
+    Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);
+    if (FastB2BSupport && EFI_ERROR (Status)) {
+      FastB2BSupport = FALSE;
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+  //
+  // Set or clear Fast Back to Back bit for the whole bridge
+  //
+  if (!IsListEmpty (&PciIoDevice->ChildList)) {
+
+    if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
+
+      Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET);
+
+      if (EFI_ERROR (Status) || (!FastB2BSupport)) {
+        FastB2BSupport = FALSE;
+        PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
+      } else {
+        PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
+      }
+    }
+
+    CurrentLink = PciIoDevice->ChildList.ForwardLink;
+    while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
+      Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+      if (FastB2BSupport) {
+        PCI_ENABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
+      } else {
+        PCI_DISABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
+      }
+
+      CurrentLink = CurrentLink->ForwardLink;
+    }
+  }
+  //
+  // End for IsListEmpty
+  //
+  return EFI_SUCCESS;
+}
+
+/**
+  This routine is used to update the bar information for those incompatible PCI device.
+
+  @param PciIoDevice      Input Pci device instance. Output Pci device instance with updated
+                          Bar information.
+
+  @retval EFI_SUCCESS     Successfully updated bar information.
+  @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.
+
+**/
+EFI_STATUS
+UpdatePciInfo (
+  IN OUT PCI_IO_DEVICE    *PciIoDevice
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             BarIndex;
+  BOOLEAN                           SetFlag;
+  VOID                              *Configuration;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+
+  Configuration = NULL;
+  Status        = EFI_SUCCESS;
+
+  if (gIncompatiblePciDeviceSupport == NULL) {
+    //
+    // It can only be supported after the Incompatible PCI Device
+    // Support Protocol has been installed
+    //
+    Status = gBS->LocateProtocol (
+                    &gEfiIncompatiblePciDeviceSupportProtocolGuid,
+                    NULL,
+                    (VOID **) &gIncompatiblePciDeviceSupport
+                    );
+  }
+  if (Status == EFI_SUCCESS) {
+      //
+      // Check whether the device belongs to incompatible devices from protocol or not
+      // If it is , then get its special requirement in the ACPI table
+      //
+      Status = gIncompatiblePciDeviceSupport->CheckDevice (
+                                                gIncompatiblePciDeviceSupport,
+                                                PciIoDevice->Pci.Hdr.VendorId,
+                                                PciIoDevice->Pci.Hdr.DeviceId,
+                                                PciIoDevice->Pci.Hdr.RevisionID,
+                                                PciIoDevice->Pci.Device.SubsystemVendorID,
+                                                PciIoDevice->Pci.Device.SubsystemID,
+                                                &Configuration
+                                                );
+
+  }
+
+  if (EFI_ERROR (Status) || Configuration == NULL ) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Update PCI device information from the ACPI table
+  //
+  Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
+
+  while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) {
+
+    if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+      //
+      // The format is not support
+      //
+      break;
+    }
+
+    for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {
+      if ((Ptr->AddrTranslationOffset != MAX_UINT64) &&
+          (Ptr->AddrTranslationOffset != MAX_UINT8) &&
+          (Ptr->AddrTranslationOffset != BarIndex)
+          ) {
+        //
+        // Skip updating when AddrTranslationOffset is not MAX_UINT64 or MAX_UINT8 (wide match).
+        // Skip updating when current BarIndex doesn't equal to AddrTranslationOffset.
+        // Comparing against MAX_UINT8 is to keep backward compatibility.
+        //
+        continue;
+      }
+
+      SetFlag = FALSE;
+      switch (Ptr->ResType) {
+      case ACPI_ADDRESS_SPACE_TYPE_MEM:
+
+        //
+        // Make sure the bar is memory type
+        //
+        if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) {
+          SetFlag = TRUE;
+
+          //
+          // Ignored if granularity is 0.
+          // Ignored if PCI BAR is I/O or 32-bit memory.
+          // If PCI BAR is 64-bit memory and granularity is 32, then
+          // the PCI BAR resource is allocated below 4GB.
+          // If PCI BAR is 64-bit memory and granularity is 64, then
+          // the PCI BAR resource is allocated above 4GB.
+          //
+          if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeMem64) {
+            switch (Ptr->AddrSpaceGranularity) {
+            case 32:
+              PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
+            case 64:
+              PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;
+              break;
+            default:
+              break;
+            }
+          }
+
+          if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypePMem64) {
+            switch (Ptr->AddrSpaceGranularity) {
+            case 32:
+              PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
+            case 64:
+              PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;
+              break;
+            default:
+              break;
+            }
+          }
+        }
+        break;
+
+      case ACPI_ADDRESS_SPACE_TYPE_IO:
+
+        //
+        // Make sure the bar is IO type
+        //
+        if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeIo)) {
+          SetFlag = TRUE;
+        }
+        break;
+      }
+
+      if (SetFlag) {
+
+        //
+        // Update the new alignment for the device
+        //
+        SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax);
+
+        //
+        // Update the new length for the device
+        //
+        if (Ptr->AddrLen != 0) {
+          PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;
+        }
+      }
+    }
+
+    Ptr++;
+  }
+
+  FreePool (Configuration);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This routine will update the alignment with the new alignment.
+  Compare with OLD_ALIGN/EVEN_ALIGN/SQUAD_ALIGN/DQUAD_ALIGN is to keep
+  backward compatibility.
+
+  @param Alignment    Input Old alignment. Output updated alignment.
+  @param NewAlignment New alignment.
+
+**/
+VOID
+SetNewAlign (
+  IN OUT UINT64     *Alignment,
+  IN     UINT64     NewAlignment
+  )
+{
+  UINT64  OldAlignment;
+  UINTN   ShiftBit;
+
+  //
+  // The new alignment is the same as the original,
+  // so skip it
+  //
+  if ((NewAlignment == 0) || (NewAlignment == OLD_ALIGN)) {
+    return ;
+  }
+  //
+  // Check the validity of the parameter
+  //
+   if (NewAlignment != EVEN_ALIGN  &&
+       NewAlignment != SQUAD_ALIGN &&
+       NewAlignment != DQUAD_ALIGN ) {
+    *Alignment = NewAlignment;
+    return ;
+  }
+
+  OldAlignment  = (*Alignment) + 1;
+  ShiftBit      = 0;
+
+  //
+  // Get the first non-zero hex value of the length
+  //
+  while ((OldAlignment & 0x0F) == 0x00) {
+    OldAlignment = RShiftU64 (OldAlignment, 4);
+    ShiftBit += 4;
+  }
+
+  //
+  // Adjust the alignment to even, quad or double quad boundary
+  //
+  if (NewAlignment == EVEN_ALIGN) {
+    if ((OldAlignment & 0x01) != 0) {
+      OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);
+    }
+  } else if (NewAlignment == SQUAD_ALIGN) {
+    if ((OldAlignment & 0x03) != 0) {
+      OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);
+    }
+  } else if (NewAlignment == DQUAD_ALIGN) {
+    if ((OldAlignment & 0x07) != 0) {
+      OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);
+    }
+  }
+
+  //
+  // Update the old value
+  //
+  NewAlignment  = LShiftU64 (OldAlignment, ShiftBit) - 1;
+  *Alignment    = NewAlignment;
+
+  return ;
+}
+
+/**
+  Parse PCI IOV VF bar information and fill them into PCI device instance.
+
+  @param PciIoDevice  Pci device instance.
+  @param Offset       Bar offset.
+  @param BarIndex     Bar index.
+
+  @return Next bar offset.
+
+**/
+UINTN
+PciIovParseVfBar (
+  IN PCI_IO_DEVICE  *PciIoDevice,
+  IN UINTN          Offset,
+  IN UINTN          BarIndex
+  )
+{
+  UINT32      Value;
+  UINT32      OriginalValue;
+  UINT32      Mask;
+  EFI_STATUS  Status;
+
+  //
+  // Ensure it is called properly
+  //
+  ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);
+  if (PciIoDevice->SrIovCapabilityOffset == 0) {
+    return 0;
+  }
+
+  OriginalValue = 0;
+  Value         = 0;
+
+  Status = VfBarExisted (
+            PciIoDevice,
+            Offset,
+            &Value,
+            &OriginalValue
+            );
+
+  if (EFI_ERROR (Status)) {
+    PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;
+    PciIoDevice->VfPciBar[BarIndex].Length      = 0;
+    PciIoDevice->VfPciBar[BarIndex].Alignment   = 0;
+
+    //
+    // Scan all the BARs anyway
+    //
+    PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16) Offset;
+    return Offset + 4;
+  }
+
+  PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16) Offset;
+  if ((Value & 0x01) != 0) {
+    //
+    // Device I/Os. Impossible
+    //
+    ASSERT (FALSE);
+    return Offset + 4;
+
+  } else {
+
+    Mask  = 0xfffffff0;
+
+    PciIoDevice->VfPciBar[BarIndex].BaseAddress = OriginalValue & Mask;
+
+    switch (Value & 0x07) {
+
+    //
+    //memory space; anywhere in 32 bit address space
+    //
+    case 0x00:
+      if ((Value & 0x08) != 0) {
+        PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem32;
+      } else {
+        PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem32;
+      }
+
+      PciIoDevice->VfPciBar[BarIndex].Length    = (~(Value & Mask)) + 1;
+      PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
+
+      //
+      // Adjust Length
+      //
+      PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);
+      //
+      // Adjust Alignment
+      //
+      if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
+        PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
+      }
+
+      break;
+
+    //
+    // memory space; anywhere in 64 bit address space
+    //
+    case 0x04:
+      if ((Value & 0x08) != 0) {
+        PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem64;
+      } else {
+        PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem64;
+      }
+
+      //
+      // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
+      // is regarded as an extension for the first bar. As a result
+      // the sizing will be conducted on combined 64 bit value
+      // Here just store the masked first 32bit value for future size
+      // calculation
+      //
+      PciIoDevice->VfPciBar[BarIndex].Length    = Value & Mask;
+      PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
+
+      if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
+        PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
+      }
+
+      //
+      // Increment the offset to point to next DWORD
+      //
+      Offset += 4;
+
+      Status = VfBarExisted (
+                PciIoDevice,
+                Offset,
+                &Value,
+                &OriginalValue
+                );
+
+      if (EFI_ERROR (Status)) {
+        PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown;
+        return Offset + 4;
+      }
+
+      //
+      // Fix the length to support some special 64 bit BAR
+      //
+      Value |= ((UINT32) -1 << HighBitSet32 (Value));
+
+      //
+      // Calculate the size of 64bit bar
+      //
+      PciIoDevice->VfPciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);
+
+      PciIoDevice->VfPciBar[BarIndex].Length    = PciIoDevice->VfPciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);
+      PciIoDevice->VfPciBar[BarIndex].Length    = (~(PciIoDevice->VfPciBar[BarIndex].Length)) + 1;
+      PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
+
+      //
+      // Adjust Length
+      //
+      PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);
+      //
+      // Adjust Alignment
+      //
+      if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
+        PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
+      }
+
+      break;
+
+    //
+    // reserved
+    //
+    default:
+      PciIoDevice->VfPciBar[BarIndex].BarType   = PciBarTypeUnknown;
+      PciIoDevice->VfPciBar[BarIndex].Length    = (~(Value & Mask)) + 1;
+      PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
+
+      if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
+        PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
+      }
+
+      break;
+    }
+  }
+
+  //
+  // Check the length again so as to keep compatible with some special bars
+  //
+  if (PciIoDevice->VfPciBar[BarIndex].Length == 0) {
+    PciIoDevice->VfPciBar[BarIndex].BarType     = PciBarTypeUnknown;
+    PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;
+    PciIoDevice->VfPciBar[BarIndex].Alignment   = 0;
+  }
+
+  //
+  // Increment number of bar
+  //
+  return Offset + 4;
+}
+
+/**
+  Parse PCI bar information and fill them into PCI device instance.
+
+  @param PciIoDevice  Pci device instance.
+  @param Offset       Bar offset.
+  @param BarIndex     Bar index.
+
+  @return Next bar offset.
+
+**/
+UINTN
+PciParseBar (
+  IN PCI_IO_DEVICE  *PciIoDevice,
+  IN UINTN          Offset,
+  IN UINTN          BarIndex
+  )
+{
+  UINT32      Value;
+  UINT32      OriginalValue;
+  UINT32      Mask;
+  EFI_STATUS  Status;
+
+  OriginalValue = 0;
+  Value         = 0;
+
+  Status = BarExisted (
+             PciIoDevice,
+             Offset,
+             &Value,
+             &OriginalValue
+             );
+
+  if (EFI_ERROR (Status)) {
+    PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
+    PciIoDevice->PciBar[BarIndex].Length      = 0;
+    PciIoDevice->PciBar[BarIndex].Alignment   = 0;
+
+    //
+    // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
+    //
+    PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
+    return Offset + 4;
+  }
+
+  PciIoDevice->PciBar[BarIndex].BarTypeFixed = FALSE;
+  PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
+  if ((Value & 0x01) != 0) {
+    //
+    // Device I/Os
+    //
+    Mask = 0xfffffffc;
+
+    if ((Value & 0xFFFF0000) != 0) {
+      //
+      // It is a IO32 bar
+      //
+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo32;
+      PciIoDevice->PciBar[BarIndex].Length    = ((~(Value & Mask)) + 1);
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+    } else {
+      //
+      // It is a IO16 bar
+      //
+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo16;
+      PciIoDevice->PciBar[BarIndex].Length    = 0x0000FFFF & ((~(Value & Mask)) + 1);
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+    }
+    //
+    // Workaround. Some platforms implement IO bar with 0 length
+    // Need to treat it as no-bar
+    //
+    if (PciIoDevice->PciBar[BarIndex].Length == 0) {
+      PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE) 0;
+    }
+
+    PciIoDevice->PciBar[BarIndex].BaseAddress   = OriginalValue & Mask;
+
+  } else {
+
+    Mask  = 0xfffffff0;
+
+    PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
+
+    switch (Value & 0x07) {
+
+    //
+    //memory space; anywhere in 32 bit address space
+    //
+    case 0x00:
+      if ((Value & 0x08) != 0) {
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
+      } else {
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
+      }
+
+      PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;
+      if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
+        //
+        // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
+        //
+        PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
+      } else {
+        PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+      }
+      break;
+
+    //
+    // memory space; anywhere in 64 bit address space
+    //
+    case 0x04:
+      if ((Value & 0x08) != 0) {
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;
+      } else {
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;
+      }
+
+      //
+      // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
+      // is regarded as an extension for the first bar. As a result
+      // the sizing will be conducted on combined 64 bit value
+      // Here just store the masked first 32bit value for future size
+      // calculation
+      //
+      PciIoDevice->PciBar[BarIndex].Length    = Value & Mask;
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+      //
+      // Increment the offset to point to next DWORD
+      //
+      Offset += 4;
+
+      Status = BarExisted (
+                 PciIoDevice,
+                 Offset,
+                 &Value,
+                 &OriginalValue
+                 );
+
+      if (EFI_ERROR (Status)) {
+        //
+        // the high 32 bit does not claim any BAR, we need to re-check the low 32 bit BAR again
+        //
+        if (PciIoDevice->PciBar[BarIndex].Length == 0) {
+          //
+          // some device implement MMIO bar with 0 length, need to treat it as no-bar
+          //
+          PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
+          return Offset + 4;
+        }
+      }
+
+      //
+      // Fix the length to support some special 64 bit BAR
+      //
+      if (Value == 0) {
+        DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n"));
+        Value = (UINT32) -1;
+      } else {
+        Value |= ((UINT32)(-1) << HighBitSet32 (Value));
+      }
+
+      //
+      // Calculate the size of 64bit bar
+      //
+      PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);
+
+      PciIoDevice->PciBar[BarIndex].Length    = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);
+      PciIoDevice->PciBar[BarIndex].Length    = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;
+      if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
+        //
+        // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
+        //
+        PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
+      } else {
+        PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+      }
+
+      break;
+
+    //
+    // reserved
+    //
+    default:
+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeUnknown;
+      PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;
+      if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
+        //
+        // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
+        //
+        PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
+      } else {
+        PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+      }
+      break;
+    }
+  }
+
+  //
+  // Check the length again so as to keep compatible with some special bars
+  //
+  if (PciIoDevice->PciBar[BarIndex].Length == 0) {
+    PciIoDevice->PciBar[BarIndex].BarType     = PciBarTypeUnknown;
+    PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
+    PciIoDevice->PciBar[BarIndex].Alignment   = 0;
+  }
+
+  //
+  // Increment number of bar
+  //
+  return Offset + 4;
+}
+
+/**
+  This routine is used to initialize the bar of a PCI device.
+
+  @param PciIoDevice Pci device instance.
+
+  @note It can be called typically when a device is going to be rejected.
+
+**/
+VOID
+InitializePciDevice (
+  IN PCI_IO_DEVICE    *PciIoDevice
+  )
+{
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  UINT8               Offset;
+
+  PciIo = &(PciIoDevice->PciIo);
+
+  //
+  // Put all the resource apertures
+  // Resource base is set to all ones so as to indicate its resource
+  // has not been allocated
+  //
+  for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {
+    PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);
+  }
+}
+
+/**
+  This routine is used to initialize the bar of a PCI-PCI Bridge device.
+
+  @param  PciIoDevice PCI-PCI bridge device instance.
+
+**/
+VOID
+InitializePpb (
+  IN PCI_IO_DEVICE    *PciIoDevice
+  )
+{
+  EFI_PCI_IO_PROTOCOL *PciIo;
+
+  PciIo = &(PciIoDevice->PciIo);
+
+  //
+  // Put all the resource apertures including IO16
+  // Io32, pMem32, pMem64 to quiescent state
+  // Resource base all ones, Resource limit all zeros
+  //
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);
+
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);
+
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);
+
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);
+
+  //
+  // Don't support use io32 as for now
+  //
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);
+
+  //
+  // Force Interrupt line to zero for cards that come up randomly
+  //
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
+}
+
+/**
+  This routine is used to initialize the bar of a PCI Card Bridge device.
+
+  @param PciIoDevice  PCI Card bridge device.
+
+**/
+VOID
+InitializeP2C (
+  IN PCI_IO_DEVICE    *PciIoDevice
+  )
+{
+  EFI_PCI_IO_PROTOCOL *PciIo;
+
+  PciIo = &(PciIoDevice->PciIo);
+
+  //
+  // Put all the resource apertures including IO16
+  // Io32, pMem32, pMem64 to quiescent state(
+  // Resource base all ones, Resource limit all zeros
+  //
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);
+
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);
+
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);
+
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);
+
+  //
+  // Force Interrupt line to zero for cards that come up randomly
+  //
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
+}
+
+/**
+  Authenticate the PCI device by using DeviceSecurityProtocol.
+
+  @param PciIoDevice  PCI device.
+
+  @retval EFI_SUCCESS     The device passes the authentication.
+  @return not EFI_SUCCESS The device failes the authentication or
+                          unexpected error happen during authentication.
+**/
+EFI_STATUS
+AuthenticatePciDevice (
+  IN PCI_IO_DEVICE            *PciIoDevice
+  )
+{
+  EDKII_DEVICE_IDENTIFIER  DeviceIdentifier;
+  EFI_STATUS               Status;
+
+  if (mDeviceSecurityProtocol != NULL) {
+    //
+    // Prepare the parameter
+    //
+    DeviceIdentifier.Version = EDKII_DEVICE_IDENTIFIER_REVISION;
+    CopyGuid (&DeviceIdentifier.DeviceType, &gEdkiiDeviceIdentifierTypePciGuid);
+    DeviceIdentifier.DeviceHandle = NULL;
+    Status = gBS->InstallMultipleProtocolInterfaces (
+                    &DeviceIdentifier.DeviceHandle,
+                    &gEfiDevicePathProtocolGuid,
+                    PciIoDevice->DevicePath,
+                    &gEdkiiDeviceIdentifierTypePciGuid,
+                    &PciIoDevice->PciIo,
+                    NULL
+                    );
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+
+    //
+    // Do DeviceAuthentication
+    //
+    Status = mDeviceSecurityProtocol->DeviceAuthenticate (mDeviceSecurityProtocol, &DeviceIdentifier);
+    //
+    // Always uninstall, because they are only for Authentication.
+    // No need to check return Status.
+    //
+    gBS->UninstallMultipleProtocolInterfaces (
+                    DeviceIdentifier.DeviceHandle,
+                    &gEfiDevicePathProtocolGuid,
+                    PciIoDevice->DevicePath,
+                    &gEdkiiDeviceIdentifierTypePciGuid,
+                    &PciIoDevice->PciIo,
+                    NULL
+                    );
+    return Status;
+  }
+
+  //
+  // Device Security Protocol is not found, just return success
+  //
+  return EFI_SUCCESS;
+}
+
+/**
+  Create and initialize general PCI I/O device instance for
+  PCI device/bridge device/hotplug bridge device.
+
+  @param Bridge            Parent bridge instance.
+  @param Pci               Input Pci information block.
+  @param Bus               Device Bus NO.
+  @param Device            Device device NO.
+  @param Func              Device func NO.
+
+  @return Instance of PCI device. NULL means no instance created.
+
+**/
+PCI_IO_DEVICE *
+CreatePciIoDevice (
+  IN PCI_IO_DEVICE                    *Bridge,
+  IN PCI_TYPE00                       *Pci,
+  IN UINT8                            Bus,
+  IN UINT8                            Device,
+  IN UINT8                            Func
+  )
+{
+  PCI_IO_DEVICE        *PciIoDevice;
+  EFI_PCI_IO_PROTOCOL  *PciIo;
+  EFI_STATUS           Status;
+
+  PciIoDevice = AllocateZeroPool (sizeof (PCI_IO_DEVICE));
+  if (PciIoDevice == NULL) {
+    return NULL;
+  }
+
+  PciIoDevice->Signature        = PCI_IO_DEVICE_SIGNATURE;
+  PciIoDevice->Handle           = NULL;
+  PciIoDevice->PciRootBridgeIo  = Bridge->PciRootBridgeIo;
+  PciIoDevice->DevicePath       = NULL;
+  PciIoDevice->BusNumber        = Bus;
+  PciIoDevice->DeviceNumber     = Device;
+  PciIoDevice->FunctionNumber   = Func;
+  PciIoDevice->Decodes          = 0;
+
+  if (gFullEnumeration) {
+    PciIoDevice->Allocated = FALSE;
+  } else {
+    PciIoDevice->Allocated = TRUE;
+  }
+
+  PciIoDevice->Registered         = FALSE;
+  PciIoDevice->Attributes         = 0;
+  PciIoDevice->Supports           = 0;
+  PciIoDevice->BusOverride        = FALSE;
+  PciIoDevice->AllOpRomProcessed  = FALSE;
+
+  PciIoDevice->IsPciExp           = FALSE;
+
+  CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));
+
+  //
+  // Initialize the PCI I/O instance structure
+  //
+  InitializePciIoInstance (PciIoDevice);
+  InitializePciDriverOverrideInstance (PciIoDevice);
+  InitializePciLoadFile2 (PciIoDevice);
+  PciIo = &PciIoDevice->PciIo;
+
+  //
+  // Create a device path for this PCI device and store it into its private data
+  //
+  CreatePciDevicePath (
+    Bridge->DevicePath,
+    PciIoDevice
+    );
+
+  //
+  // Detect if PCI Express Device
+  //
+  PciIoDevice->PciExpressCapabilityOffset = 0;
+  Status = LocateCapabilityRegBlock (
+             PciIoDevice,
+             EFI_PCI_CAPABILITY_ID_PCIEXP,
+             &PciIoDevice->PciExpressCapabilityOffset,
+             NULL
+             );
+  if (!EFI_ERROR (Status)) {
+    PciIoDevice->IsPciExp = TRUE;
+  }
+
+  //
+  // Now we can do the authentication check for the device.
+  //
+  Status = AuthenticatePciDevice (PciIoDevice);
+  //
+  // If authentication fails, skip this device.
+  //
+  if (EFI_ERROR(Status)) {
+    if (PciIoDevice->DevicePath != NULL) {
+      FreePool (PciIoDevice->DevicePath);
+    }
+    FreePool (PciIoDevice);
+    return NULL;
+  }
+
+  if (PcdGetBool (PcdAriSupport)) {
+    //
+    // Check if the device is an ARI device.
+    //
+    Status = LocatePciExpressCapabilityRegBlock (
+               PciIoDevice,
+               EFI_PCIE_CAPABILITY_ID_ARI,
+               &PciIoDevice->AriCapabilityOffset,
+               NULL
+               );
+    if (!EFI_ERROR (Status)) {
+      //
+      // We need to enable ARI feature before calculate BusReservation,
+      // because FirstVFOffset and VFStride may change after that.
+      //
+      EFI_PCI_IO_PROTOCOL  *ParentPciIo;
+      UINT32               Data32;
+
+      //
+      // Check if its parent supports ARI forwarding.
+      //
+      ParentPciIo = &Bridge->PciIo;
+      ParentPciIo->Pci.Read (
+                          ParentPciIo,
+                          EfiPciIoWidthUint32,
+                          Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET,
+                          1,
+                          &Data32
+                          );
+      if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING) != 0) {
+        //
+        // ARI forward support in bridge, so enable it.
+        //
+        ParentPciIo->Pci.Read (
+                            ParentPciIo,
+                            EfiPciIoWidthUint32,
+                            Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,
+                            1,
+                            &Data32
+                            );
+        if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING) == 0) {
+          Data32 |= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING;
+          ParentPciIo->Pci.Write (
+                              ParentPciIo,
+                              EfiPciIoWidthUint32,
+                              Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,
+                              1,
+                              &Data32
+                              );
+          DEBUG ((
+            EFI_D_INFO,
+            " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
+            Bridge->BusNumber,
+            Bridge->DeviceNumber,
+            Bridge->FunctionNumber
+            ));
+        }
+      }
+
+      DEBUG ((EFI_D_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice->AriCapabilityOffset));
+    }
+  }
+
+  //
+  // Initialization for SR-IOV
+  //
+
+  if (PcdGetBool (PcdSrIovSupport)) {
+    Status = LocatePciExpressCapabilityRegBlock (
+               PciIoDevice,
+               EFI_PCIE_CAPABILITY_ID_SRIOV,
+               &PciIoDevice->SrIovCapabilityOffset,
+               NULL
+               );
+    if (!EFI_ERROR (Status)) {
+      UINT32    SupportedPageSize;
+      UINT16    VFStride;
+      UINT16    FirstVFOffset;
+      UINT16    Data16;
+      UINT32    PFRid;
+      UINT32    LastVF;
+
+      //
+      // If the SR-IOV device is an ARI device, then Set ARI Capable Hierarchy for the device.
+      //
+      if (PcdGetBool (PcdAriSupport) && PciIoDevice->AriCapabilityOffset != 0) {
+        PciIo->Pci.Read (
+                     PciIo,
+                     EfiPciIoWidthUint16,
+                     PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,
+                     1,
+                     &Data16
+                     );
+        Data16 |= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY;
+        PciIo->Pci.Write (
+                     PciIo,
+                     EfiPciIoWidthUint16,
+                     PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,
+                     1,
+                     &Data16
+                     );
+      }
+
+      //
+      // Calculate SystemPageSize
+      //
+
+      PciIo->Pci.Read (
+                   PciIo,
+                   EfiPciIoWidthUint32,
+                   PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE,
+                   1,
+                   &SupportedPageSize
+                   );
+      PciIoDevice->SystemPageSize = (PcdGet32 (PcdSrIovSystemPageSize) & SupportedPageSize);
+      ASSERT (PciIoDevice->SystemPageSize != 0);
+
+      PciIo->Pci.Write (
+                   PciIo,
+                   EfiPciIoWidthUint32,
+                   PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE,
+                   1,
+                   &PciIoDevice->SystemPageSize
+                   );
+      //
+      // Adjust SystemPageSize for Alignment usage later
+      //
+      PciIoDevice->SystemPageSize <<= 12;
+
+      //
+      // Calculate BusReservation for PCI IOV
+      //
+
+      //
+      // Read First FirstVFOffset, InitialVFs, and VFStride
+      //
+      PciIo->Pci.Read (
+                   PciIo,
+                   EfiPciIoWidthUint16,
+                   PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF,
+                   1,
+                   &FirstVFOffset
+                   );
+      PciIo->Pci.Read (
+                   PciIo,
+                   EfiPciIoWidthUint16,
+                   PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS,
+                   1,
+                   &PciIoDevice->InitialVFs
+                   );
+      PciIo->Pci.Read (
+                   PciIo,
+                   EfiPciIoWidthUint16,
+                   PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE,
+                   1,
+                   &VFStride
+                   );
+      //
+      // Calculate LastVF
+      //
+      PFRid = EFI_PCI_RID(Bus, Device, Func);
+      LastVF = PFRid + FirstVFOffset + (PciIoDevice->InitialVFs - 1) * VFStride;
+
+      //
+      // Calculate ReservedBusNum for this PF
+      //
+      PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus + 1);
+
+      DEBUG ((
+        EFI_D_INFO,
+        " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x; FirstVFOffset = 0x%x;\n",
+        SupportedPageSize, PciIoDevice->SystemPageSize >> 12, FirstVFOffset
+        ));
+      DEBUG ((
+        EFI_D_INFO,
+        "         InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n",
+        PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum, PciIoDevice->SrIovCapabilityOffset
+        ));
+    }
+  }
+
+  if (PcdGetBool (PcdMrIovSupport)) {
+    Status = LocatePciExpressCapabilityRegBlock (
+               PciIoDevice,
+               EFI_PCIE_CAPABILITY_ID_MRIOV,
+               &PciIoDevice->MrIovCapabilityOffset,
+               NULL
+               );
+    if (!EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice->MrIovCapabilityOffset));
+    }
+  }
+
+  PciIoDevice->ResizableBarOffset = 0;
+  if (PcdGetBool (PcdPcieResizableBarSupport)) {
+    Status = LocatePciExpressCapabilityRegBlock (
+               PciIoDevice,
+               PCI_EXPRESS_EXTENDED_CAPABILITY_RESIZABLE_BAR_ID,
+               &PciIoDevice->ResizableBarOffset,
+               NULL
+               );
+    if (!EFI_ERROR (Status)) {
+      PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL ResizableBarControl;
+      UINT32                                                  Offset;
+      Offset = PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER)
+                + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CAPABILITY),
+      PciIo->Pci.Read (
+              PciIo,
+              EfiPciIoWidthUint8,
+              Offset,
+              sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL),
+              &ResizableBarControl
+              );
+      PciIoDevice->ResizableBarNumber = ResizableBarControl.Bits.ResizableBarNumber;
+      PciProgramResizableBar (PciIoDevice, PciResizableBarMax);
+    }
+  }
+
+  //
+  // Initialize the reserved resource list
+  //
+  InitializeListHead (&PciIoDevice->ReservedResourceList);
+
+  //
+  // Initialize the driver list
+  //
+  InitializeListHead (&PciIoDevice->OptionRomDriverList);
+
+  //
+  // Initialize the child list
+  //
+  InitializeListHead (&PciIoDevice->ChildList);
+
+  return PciIoDevice;
+}
+
+/**
+  This routine is used to enumerate entire pci bus system
+  in a given platform.
+
+  It is only called on the second start on the same Root Bridge.
+
+  @param  Controller     Parent bridge handler.
+
+  @retval EFI_SUCCESS    PCI enumeration finished successfully.
+  @retval other          Some error occurred when enumerating the pci bus system.
+
+**/
+EFI_STATUS
+PciEnumeratorLight (
+  IN EFI_HANDLE                    Controller
+  )
+{
+
+  EFI_STATUS                        Status;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;
+  PCI_IO_DEVICE                     *RootBridgeDev;
+  UINT16                            MinBus;
+  UINT16                            MaxBus;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+
+  MinBus      = 0;
+  MaxBus      = PCI_MAX_BUS;
+  Descriptors = NULL;
+
+  //
+  // If this root bridge has been already enumerated, then return successfully
+  //
+  if (GetRootBridgeByHandle (Controller) != NULL) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Open pci root bridge io protocol
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciRootBridgeIoProtocolGuid,
+                  (VOID **) &PciRootBridgeIo,
+                  gPciBusDriverBinding.DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+    return Status;
+  }
+
+  Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {
+
+    //
+    // Create a device node for root bridge device with a NULL host bridge controller handle
+    //
+    RootBridgeDev = CreateRootBridge (Controller);
+
+    if (RootBridgeDev == NULL) {
+      Descriptors++;
+      continue;
+    }
+
+    //
+    // Record the root bridge-io protocol
+    //
+    RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
+
+    Status = PciPciDeviceInfoCollector (
+               RootBridgeDev,
+               (UINT8) MinBus
+               );
+
+    if (!EFI_ERROR (Status)) {
+
+      //
+      // Remove those PCI devices which are rejected when full enumeration
+      //
+      RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev);
+
+      //
+      // Process option rom light
+      //
+      ProcessOptionRomLight (RootBridgeDev);
+
+      //
+      // Determine attributes for all devices under this root bridge
+      //
+      DetermineDeviceAttribute (RootBridgeDev);
+
+      //
+      // If successfully, insert the node into device pool
+      //
+      InsertRootBridge (RootBridgeDev);
+    } else {
+
+      //
+      // If unsuccessfully, destroy the entire node
+      //
+      DestroyRootBridge (RootBridgeDev);
+    }
+
+    Descriptors++;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get bus range from PCI resource descriptor list.
+
+  @param Descriptors  A pointer to the address space descriptor.
+  @param MinBus       The min bus returned.
+  @param MaxBus       The max bus returned.
+  @param BusRange     The bus range returned.
+
+  @retval EFI_SUCCESS    Successfully got bus range.
+  @retval EFI_NOT_FOUND  Can not find the specific bus.
+
+**/
+EFI_STATUS
+PciGetBusRange (
+  IN     EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors,
+  OUT    UINT16                             *MinBus,
+  OUT    UINT16                             *MaxBus,
+  OUT    UINT16                             *BusRange
+  )
+{
+  while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
+    if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
+      if (MinBus != NULL) {
+        *MinBus = (UINT16) (*Descriptors)->AddrRangeMin;
+      }
+
+      if (MaxBus != NULL) {
+        *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax;
+      }
+
+      if (BusRange != NULL) {
+        *BusRange = (UINT16) (*Descriptors)->AddrLen;
+      }
+
+      return EFI_SUCCESS;
+    }
+
+    (*Descriptors)++;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  This routine can be used to start the root bridge.
+
+  @param RootBridgeDev     Pci device instance.
+
+  @retval EFI_SUCCESS      This device started.
+  @retval other            Failed to get PCI Root Bridge I/O protocol.
+
+**/
+EFI_STATUS
+StartManagingRootBridge (
+  IN PCI_IO_DEVICE *RootBridgeDev
+  )
+{
+  EFI_HANDLE                      RootBridgeHandle;
+  EFI_STATUS                      Status;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+  //
+  // Get the root bridge handle
+  //
+  RootBridgeHandle = RootBridgeDev->Handle;
+  PciRootBridgeIo  = NULL;
+
+  //
+  // Get the pci root bridge io protocol
+  //
+  Status = gBS->OpenProtocol (
+                  RootBridgeHandle,
+                  &gEfiPciRootBridgeIoProtocolGuid,
+                  (VOID **) &PciRootBridgeIo,
+                  gPciBusDriverBinding.DriverBindingHandle,
+                  RootBridgeHandle,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+    return Status;
+  }
+
+  //
+  // Store the PciRootBridgeIo protocol into root bridge private data
+  //
+  RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
+
+  return EFI_SUCCESS;
+
+}
+
+/**
+  This routine can be used to check whether a PCI device should be rejected when light enumeration.
+
+  @param PciIoDevice  Pci device instance.
+
+  @retval TRUE      This device should be rejected.
+  @retval FALSE     This device shouldn't be rejected.
+
+**/
+BOOLEAN
+IsPciDeviceRejected (
+  IN PCI_IO_DEVICE *PciIoDevice
+  )
+{
+  EFI_STATUS  Status;
+  UINT32      TestValue;
+  UINT32      OldValue;
+  UINT32      Mask;
+  UINT8       BarOffset;
+
+  //
+  // PPB should be skip!
+  //
+  if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
+    return FALSE;
+  }
+
+  if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+    //
+    // Only test base registers for P2C
+    //
+    for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) {
+
+      Mask    = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
+      Status  = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
+      if (EFI_ERROR (Status)) {
+        continue;
+      }
+
+      TestValue = TestValue & Mask;
+      if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
+        //
+        // The bar isn't programed, so it should be rejected
+        //
+        return TRUE;
+      }
+    }
+
+    return FALSE;
+  }
+
+  for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) {
+    //
+    // Test PCI devices
+    //
+    Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+
+    if ((TestValue & 0x01) != 0) {
+
+      //
+      // IO Bar
+      //
+      Mask      = 0xFFFFFFFC;
+      TestValue = TestValue & Mask;
+      if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
+        return TRUE;
+      }
+
+    } else {
+
+      //
+      // Mem Bar
+      //
+      Mask      = 0xFFFFFFF0;
+      TestValue = TestValue & Mask;
+
+      if ((TestValue & 0x07) == 0x04) {
+
+        //
+        // Mem64 or PMem64
+        //
+        BarOffset += sizeof (UINT32);
+        if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
+
+          //
+          // Test its high 32-Bit BAR
+          //
+          Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
+          if (TestValue == OldValue) {
+            return TRUE;
+          }
+        }
+
+      } else {
+
+        //
+        // Mem32 or PMem32
+        //
+        if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
+          return TRUE;
+        }
+      }
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  Reset all bus number from specific bridge.
+
+  @param Bridge           Parent specific bridge.
+  @param StartBusNumber   Start bus number.
+
+**/
+VOID
+ResetAllPpbBusNumber (
+  IN PCI_IO_DEVICE                      *Bridge,
+  IN UINT8                              StartBusNumber
+  )
+{
+  EFI_STATUS                      Status;
+  PCI_TYPE00                      Pci;
+  UINT8                           Device;
+  UINT32                          Register;
+  UINT8                           Func;
+  UINT64                          Address;
+  UINT8                           SecondaryBus;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+  PciRootBridgeIo = Bridge->PciRootBridgeIo;
+
+  for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+
+      //
+      // Check to see whether a pci device is present
+      //
+      Status = PciDevicePresent (
+                 PciRootBridgeIo,
+                 &Pci,
+                 StartBusNumber,
+                 Device,
+                 Func
+                 );
+
+      if (EFI_ERROR (Status) && Func == 0) {
+        //
+        // go to next device if there is no Function 0
+        //
+        break;
+      }
+
+      if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {
+
+        Register  = 0;
+        Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
+        Status    = PciRootBridgeIo->Pci.Read (
+                                           PciRootBridgeIo,
+                                           EfiPciWidthUint32,
+                                           Address,
+                                           1,
+                                           &Register
+                                           );
+        SecondaryBus = (UINT8)(Register >> 8);
+
+        if (SecondaryBus != 0) {
+          ResetAllPpbBusNumber (Bridge, SecondaryBus);
+        }
+
+        //
+        // Reset register 18h, 19h, 1Ah on PCI Bridge
+        //
+        Register &= 0xFF000000;
+        Status = PciRootBridgeIo->Pci.Write (
+                                        PciRootBridgeIo,
+                                        EfiPciWidthUint32,
+                                        Address,
+                                        1,
+                                        &Register
+                                        );
+      }
+
+      if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
+        //
+        // Skip sub functions, this is not a multi function device
+        //
+        Func = PCI_MAX_FUNC;
+      }
+    }
+  }
+}
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h
new file mode 100644
index 0000000000..1d39c5171d
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h
@@ -0,0 +1,480 @@
+/** @file
+  PCI enumeration support functions declaration for PCI Bus module.
+
+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_PCI_ENUMERATOR_SUPPORT_H_
+#define _EFI_PCI_ENUMERATOR_SUPPORT_H_
+
+/**
+  This routine is used to check whether the pci device is present.
+
+  @param PciRootBridgeIo   Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param Pci               Output buffer for PCI device configuration space.
+  @param Bus               PCI bus NO.
+  @param Device            PCI device NO.
+  @param Func              PCI Func NO.
+
+  @retval EFI_NOT_FOUND    PCI device not present.
+  @retval EFI_SUCCESS      PCI device is found.
+
+**/
+EFI_STATUS
+PciDevicePresent (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL     *PciRootBridgeIo,
+  OUT PCI_TYPE00                          *Pci,
+  IN  UINT8                               Bus,
+  IN  UINT8                               Device,
+  IN  UINT8                               Func
+  );
+
+/**
+  Collect all the resource information under this root bridge.
+
+  A database that records all the information about pci device subject to this
+  root bridge will then be created.
+
+  @param Bridge         Parent bridge instance.
+  @param StartBusNumber Bus number of beginning.
+
+  @retval EFI_SUCCESS   PCI device is found.
+  @retval other         Some error occurred when reading PCI bridge information.
+
+**/
+EFI_STATUS
+PciPciDeviceInfoCollector (
+  IN PCI_IO_DEVICE                      *Bridge,
+  IN UINT8                              StartBusNumber
+  );
+
+/**
+  Search required device and create PCI device instance.
+
+  @param Bridge     Parent bridge instance.
+  @param Pci        Input PCI device information block.
+  @param Bus        PCI bus NO.
+  @param Device     PCI device NO.
+  @param Func       PCI func  NO.
+  @param PciDevice  Output of searched PCI device instance.
+
+  @retval EFI_SUCCESS           Successfully created PCI device instance.
+  @retval EFI_OUT_OF_RESOURCES  Cannot get PCI device information.
+
+**/
+EFI_STATUS
+PciSearchDevice (
+  IN  PCI_IO_DEVICE                         *Bridge,
+  IN  PCI_TYPE00                            *Pci,
+  IN  UINT8                                 Bus,
+  IN  UINT8                                 Device,
+  IN  UINT8                                 Func,
+  OUT PCI_IO_DEVICE                         **PciDevice
+  );
+
+/**
+  Create PCI device instance for PCI device.
+
+  @param Bridge   Parent bridge instance.
+  @param Pci      Input PCI device information block.
+  @param Bus      PCI device Bus NO.
+  @param Device   PCI device Device NO.
+  @param Func     PCI device's func NO.
+
+  @return  Created PCI device instance.
+
+**/
+PCI_IO_DEVICE *
+GatherDeviceInfo (
+  IN PCI_IO_DEVICE                    *Bridge,
+  IN PCI_TYPE00                       *Pci,
+  IN UINT8                            Bus,
+  IN UINT8                            Device,
+  IN UINT8                            Func
+  );
+
+/**
+  Create PCI device instance for PCI-PCI bridge.
+
+  @param Bridge   Parent bridge instance.
+  @param Pci      Input PCI device information block.
+  @param Bus      PCI device Bus NO.
+  @param Device   PCI device Device NO.
+  @param Func     PCI device's func NO.
+
+  @return  Created PCI device instance.
+
+**/
+PCI_IO_DEVICE *
+GatherPpbInfo (
+  IN PCI_IO_DEVICE                    *Bridge,
+  IN PCI_TYPE00                       *Pci,
+  IN UINT8                            Bus,
+  IN UINT8                            Device,
+  IN UINT8                            Func
+  );
+
+/**
+  Create PCI device instance for PCI Card bridge device.
+
+  @param Bridge   Parent bridge instance.
+  @param Pci      Input PCI device information block.
+  @param Bus      PCI device Bus NO.
+  @param Device   PCI device Device NO.
+  @param Func     PCI device's func NO.
+
+  @return  Created PCI device instance.
+
+**/
+PCI_IO_DEVICE *
+GatherP2CInfo (
+  IN PCI_IO_DEVICE                    *Bridge,
+  IN PCI_TYPE00                       *Pci,
+  IN UINT8                            Bus,
+  IN UINT8                            Device,
+  IN UINT8                            Func
+  );
+
+/**
+  Create device path for pci device.
+
+  @param ParentDevicePath  Parent bridge's path.
+  @param PciIoDevice       Pci device instance.
+
+  @return Device path protocol instance for specific pci device.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+CreatePciDevicePath (
+  IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+  IN  PCI_IO_DEVICE            *PciIoDevice
+  );
+
+/**
+  Check whether the PCI IOV VF bar is existed or not.
+
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.
+  @param Offset            The offset.
+  @param BarLengthValue    The bar length value returned.
+  @param OriginalBarValue  The original bar value returned.
+
+  @retval EFI_NOT_FOUND    The bar doesn't exist.
+  @retval EFI_SUCCESS      The bar exist.
+
+**/
+EFI_STATUS
+VfBarExisted (
+  IN PCI_IO_DEVICE *PciIoDevice,
+  IN UINTN         Offset,
+  OUT UINT32       *BarLengthValue,
+  OUT UINT32       *OriginalBarValue
+  );
+
+/**
+  Check whether the bar is existed or not.
+
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.
+  @param Offset            The offset.
+  @param BarLengthValue    The bar length value returned.
+  @param OriginalBarValue  The original bar value returned.
+
+  @retval EFI_NOT_FOUND    The bar doesn't exist.
+  @retval EFI_SUCCESS      The bar exist.
+
+**/
+EFI_STATUS
+BarExisted (
+  IN  PCI_IO_DEVICE *PciIoDevice,
+  IN  UINTN         Offset,
+  OUT UINT32        *BarLengthValue,
+  OUT UINT32        *OriginalBarValue
+  );
+
+/**
+  Test whether the device can support given attributes.
+
+  @param PciIoDevice      Pci device instance.
+  @param Command          Input command register value, and
+                          returned supported register value.
+  @param BridgeControl    Input bridge control value for PPB or P2C, and
+                          returned supported bridge control value.
+  @param OldCommand       Returned and stored old command register offset.
+  @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.
+
+**/
+VOID
+PciTestSupportedAttribute (
+  IN     PCI_IO_DEVICE                      *PciIoDevice,
+  IN OUT UINT16                             *Command,
+  IN OUT UINT16                             *BridgeControl,
+     OUT UINT16                             *OldCommand,
+     OUT UINT16                             *OldBridgeControl
+  );
+
+/**
+  Set the supported or current attributes of a PCI device.
+
+  @param PciIoDevice    Structure pointer for PCI device.
+  @param Command        Command register value.
+  @param BridgeControl  Bridge control value for PPB or P2C.
+  @param Option         Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
+
+**/
+VOID
+PciSetDeviceAttribute (
+  IN PCI_IO_DEVICE                      *PciIoDevice,
+  IN UINT16                             Command,
+  IN UINT16                             BridgeControl,
+  IN UINTN                              Option
+  );
+
+/**
+  Determine if the device can support Fast Back to Back attribute.
+
+  @param PciIoDevice  Pci device instance.
+  @param StatusIndex  Status register value.
+
+  @retval EFI_SUCCESS       This device support Fast Back to Back attribute.
+  @retval EFI_UNSUPPORTED   This device doesn't support Fast Back to Back attribute.
+
+**/
+EFI_STATUS
+GetFastBackToBackSupport (
+  IN PCI_IO_DEVICE                      *PciIoDevice,
+  IN UINT8                              StatusIndex
+  );
+
+/**
+  Determine the related attributes of all devices under a Root Bridge.
+
+  @param PciIoDevice   PCI device instance.
+
+**/
+EFI_STATUS
+DetermineDeviceAttribute (
+  IN PCI_IO_DEVICE                      *PciIoDevice
+  );
+
+/**
+  This routine is used to update the bar information for those incompatible PCI device.
+
+  @param PciIoDevice      Input Pci device instance. Output Pci device instance with updated
+                          Bar information.
+
+  @retval EFI_SUCCESS     Successfully updated bar information.
+  @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.
+
+**/
+EFI_STATUS
+UpdatePciInfo (
+  IN OUT PCI_IO_DEVICE    *PciIoDevice
+  );
+
+/**
+  This routine will update the alignment with the new alignment.
+
+  @param Alignment    Input Old alignment. Output updated alignment.
+  @param NewAlignment New alignment.
+
+**/
+VOID
+SetNewAlign (
+  IN OUT UINT64     *Alignment,
+  IN     UINT64     NewAlignment
+  );
+
+/**
+  Parse PCI bar information and fill them into PCI device instance.
+
+  @param PciIoDevice  Pci device instance.
+  @param Offset       Bar offset.
+  @param BarIndex     Bar index.
+
+  @return Next bar offset.
+
+**/
+UINTN
+PciParseBar (
+  IN PCI_IO_DEVICE  *PciIoDevice,
+  IN UINTN          Offset,
+  IN UINTN          BarIndex
+  );
+
+/**
+  Parse PCI IOV VF bar information and fill them into PCI device instance.
+
+  @param PciIoDevice  Pci device instance.
+  @param Offset       Bar offset.
+  @param BarIndex     Bar index.
+
+  @return Next bar offset.
+
+**/
+UINTN
+PciIovParseVfBar (
+  IN PCI_IO_DEVICE  *PciIoDevice,
+  IN UINTN          Offset,
+  IN UINTN          BarIndex
+  );
+
+/**
+  This routine is used to initialize the bar of a PCI device.
+
+  @param PciIoDevice Pci device instance.
+
+  @note It can be called typically when a device is going to be rejected.
+
+**/
+VOID
+InitializePciDevice (
+  IN PCI_IO_DEVICE    *PciIoDevice
+  );
+
+/**
+  This routine is used to initialize the bar of a PCI-PCI Bridge device.
+
+  @param  PciIoDevice PCI-PCI bridge device instance.
+
+**/
+VOID
+InitializePpb (
+  IN PCI_IO_DEVICE    *PciIoDevice
+  );
+
+/**
+  This routine is used to initialize the bar of a PCI Card Bridge device.
+
+  @param PciIoDevice  PCI Card bridge device.
+
+**/
+VOID
+InitializeP2C (
+  IN PCI_IO_DEVICE    *PciIoDevice
+  );
+
+/**
+  Create and initialize general PCI I/O device instance for
+  PCI device/bridge device/hotplug bridge device.
+
+  @param Bridge            Parent bridge instance.
+  @param Pci               Input Pci information block.
+  @param Bus               Device Bus NO.
+  @param Device            Device device NO.
+  @param Func              Device func NO.
+
+  @return Instance of PCI device. NULL means no instance created.
+
+**/
+PCI_IO_DEVICE *
+CreatePciIoDevice (
+  IN PCI_IO_DEVICE                    *Bridge,
+  IN PCI_TYPE00                       *Pci,
+  IN UINT8                            Bus,
+  IN UINT8                            Device,
+  IN UINT8                            Func
+  );
+
+/**
+  This routine is used to enumerate entire pci bus system
+  in a given platform.
+
+  It is only called on the second start on the same Root Bridge.
+
+  @param  Controller     Parent bridge handler.
+
+  @retval EFI_SUCCESS    PCI enumeration finished successfully.
+  @retval other          Some error occurred when enumerating the pci bus system.
+
+**/
+EFI_STATUS
+PciEnumeratorLight (
+  IN EFI_HANDLE                    Controller
+  );
+
+/**
+  Get bus range from PCI resource descriptor list.
+
+  @param Descriptors  A pointer to the address space descriptor.
+  @param MinBus       The min bus returned.
+  @param MaxBus       The max bus returned.
+  @param BusRange     The bus range returned.
+
+  @retval EFI_SUCCESS    Successfully got bus range.
+  @retval EFI_NOT_FOUND  Can not find the specific bus.
+
+**/
+EFI_STATUS
+PciGetBusRange (
+  IN     EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors,
+  OUT    UINT16                             *MinBus,
+  OUT    UINT16                             *MaxBus,
+  OUT    UINT16                             *BusRange
+  );
+
+/**
+  This routine can be used to start the root bridge.
+
+  @param RootBridgeDev     Pci device instance.
+
+  @retval EFI_SUCCESS      This device started.
+  @retval other            Failed to get PCI Root Bridge I/O protocol.
+
+**/
+EFI_STATUS
+StartManagingRootBridge (
+  IN PCI_IO_DEVICE *RootBridgeDev
+  );
+
+/**
+  This routine can be used to check whether a PCI device should be rejected when light enumeration.
+
+  @param PciIoDevice  Pci device instance.
+
+  @retval TRUE      This device should be rejected.
+  @retval FALSE     This device shouldn't be rejected.
+
+**/
+BOOLEAN
+IsPciDeviceRejected (
+  IN PCI_IO_DEVICE *PciIoDevice
+  );
+
+/**
+  Reset all bus number from specific bridge.
+
+  @param Bridge           Parent specific bridge.
+  @param StartBusNumber   Start bus number.
+
+**/
+VOID
+ResetAllPpbBusNumber (
+  IN PCI_IO_DEVICE                      *Bridge,
+  IN UINT8                              StartBusNumber
+  );
+
+/**
+  Dump the PPB padding resource information.
+
+  @param PciIoDevice     PCI IO instance.
+  @param ResourceType    The desired resource type to dump.
+                         PciBarTypeUnknown means to dump all types of resources.
+**/
+VOID
+DumpPpbPaddingResource (
+  IN PCI_IO_DEVICE                    *PciIoDevice,
+  IN PCI_BAR_TYPE                     ResourceType
+  );
+
+/**
+  Dump the PCI BAR information.
+
+  @param PciIoDevice     PCI IO instance.
+**/
+VOID
+DumpPciBars (
+  IN PCI_IO_DEVICE                    *PciIoDevice
+  );
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c
new file mode 100644
index 0000000000..d6d06b061a
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c
@@ -0,0 +1,484 @@
+/** @file
+  PCI Hot Plug support functions implementation for PCI Bus module..
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+
+EFI_PCI_HOT_PLUG_INIT_PROTOCOL  *gPciHotPlugInit = NULL;
+EFI_HPC_LOCATION                *gPciRootHpcPool = NULL;
+UINTN                           gPciRootHpcCount = 0;
+ROOT_HPC_DATA                   *gPciRootHpcData = NULL;
+
+
+/**
+  Event notification function to set Hot Plug controller status.
+
+  @param  Event                    The event that invoke this function.
+  @param  Context                  The calling context, pointer to ROOT_HPC_DATA.
+
+**/
+VOID
+EFIAPI
+PciHPCInitialized (
+  IN EFI_EVENT    Event,
+  IN VOID         *Context
+  )
+{
+  ROOT_HPC_DATA   *HpcData;
+
+  HpcData               = (ROOT_HPC_DATA *) Context;
+  HpcData->Initialized  = TRUE;
+}
+
+/**
+  Compare two device paths to check if they are exactly same.
+
+  @param DevicePath1    A pointer to the first device path data structure.
+  @param DevicePath2    A pointer to the second device path data structure.
+
+  @retval TRUE    They are same.
+  @retval FALSE   They are not same.
+
+**/
+BOOLEAN
+EfiCompareDevicePath (
+  IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
+  IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
+  )
+{
+  UINTN Size1;
+  UINTN Size2;
+
+  Size1 = GetDevicePathSize (DevicePath1);
+  Size2 = GetDevicePathSize (DevicePath2);
+
+  if (Size1 != Size2) {
+    return FALSE;
+  }
+
+  if (CompareMem (DevicePath1, DevicePath2, Size1) != 0) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+  Check hot plug support and initialize root hot plug private data.
+
+  If Hot Plug is supported by the platform, call PCI Hot Plug Init protocol
+  to get PCI Hot Plug controller's information and constructor the root hot plug
+  private data structure.
+
+  @retval EFI_SUCCESS           They are same.
+  @retval EFI_UNSUPPORTED       No PCI Hot Plug controller on the platform.
+  @retval EFI_OUT_OF_RESOURCES  No memory to constructor root hot plug private
+                                data structure.
+
+**/
+EFI_STATUS
+InitializeHotPlugSupport (
+  VOID
+  )
+{
+  EFI_STATUS        Status;
+  EFI_HPC_LOCATION  *HpcList;
+  UINTN             HpcCount;
+
+  //
+  // Locate the PciHotPlugInit Protocol
+  // If it doesn't exist, that means there is no
+  // hot plug controller supported on the platform
+  // the PCI Bus driver is running on. HotPlug Support
+  // is an optional feature, so absence of the protocol
+  // won't incur the penalty.
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiPciHotPlugInitProtocolGuid,
+                  NULL,
+                  (VOID **) &gPciHotPlugInit
+                  );
+
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = gPciHotPlugInit->GetRootHpcList (
+                              gPciHotPlugInit,
+                              &HpcCount,
+                              &HpcList
+                              );
+
+  if (!EFI_ERROR (Status)) {
+
+    gPciRootHpcPool   = HpcList;
+    gPciRootHpcCount  = HpcCount;
+    gPciRootHpcData   = AllocateZeroPool (sizeof (ROOT_HPC_DATA) * gPciRootHpcCount);
+    if (gPciRootHpcData == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Test whether device path is for root pci hot plug bus.
+
+  @param HpbDevicePath  A pointer to device path data structure to be tested.
+  @param HpIndex        If HpIndex is not NULL, return the index of root hot
+                        plug in global array when TRUE is returned.
+
+  @retval TRUE          The device path is for root pci hot plug bus.
+  @retval FALSE         The device path is not for root pci hot plug bus.
+
+**/
+BOOLEAN
+IsRootPciHotPlugBus (
+  IN  EFI_DEVICE_PATH_PROTOCOL        *HpbDevicePath,
+  OUT UINTN                           *HpIndex    OPTIONAL
+  )
+{
+  UINTN Index;
+
+  for (Index = 0; Index < gPciRootHpcCount; Index++) {
+
+    if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpbDevicePath, HpbDevicePath)) {
+
+      if (HpIndex != NULL) {
+        *HpIndex = Index;
+      }
+
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  Test whether device path is for root pci hot plug controller.
+
+  @param HpcDevicePath  A pointer to device path data structure to be tested.
+  @param HpIndex        If HpIndex is not NULL, return the index of root hot
+                        plug in global array when TRUE is returned.
+
+  @retval TRUE          The device path is for root pci hot plug controller.
+  @retval FALSE         The device path is not for root pci hot plug controller.
+
+**/
+BOOLEAN
+IsRootPciHotPlugController (
+  IN EFI_DEVICE_PATH_PROTOCOL         *HpcDevicePath,
+  OUT UINTN                           *HpIndex
+  )
+{
+  UINTN Index;
+
+  for (Index = 0; Index < gPciRootHpcCount; Index++) {
+
+    if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpcDevicePath, HpcDevicePath)) {
+
+      if (HpIndex != NULL) {
+        *HpIndex = Index;
+      }
+
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  Creating event object for PCI Hot Plug controller.
+
+  @param  HpIndex   Index of hot plug device in global array.
+  @param  Event     The returned event that invoke this function.
+
+  @return Status of create event.
+
+**/
+EFI_STATUS
+CreateEventForHpc (
+  IN  UINTN      HpIndex,
+  OUT EFI_EVENT  *Event
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = gBS->CreateEvent (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  PciHPCInitialized,
+                  gPciRootHpcData + HpIndex,
+                  &((gPciRootHpcData + HpIndex)->Event)
+                  );
+
+  if (!EFI_ERROR (Status)) {
+    *Event = (gPciRootHpcData + HpIndex)->Event;
+  }
+
+  return Status;
+}
+
+/**
+  Wait for all root PCI Hot Plug controller finished initializing.
+
+  @param TimeoutInMicroSeconds  Microseconds to wait for all root HPCs' initialization.
+
+  @retval EFI_SUCCESS           All HPCs initialization finished.
+  @retval EFI_TIMEOUT           Not ALL HPCs initialization finished in Microseconds.
+
+**/
+EFI_STATUS
+AllRootHPCInitialized (
+  IN  UINTN           TimeoutInMicroSeconds
+  )
+{
+  UINT32  Delay;
+  UINTN   Index;
+
+  Delay = (UINT32) ((TimeoutInMicroSeconds / 30) + 1);
+
+  do {
+    for (Index = 0; Index < gPciRootHpcCount; Index++) {
+
+      if (gPciRootHpcData[Index].Found && !gPciRootHpcData[Index].Initialized) {
+        break;
+      }
+    }
+
+    if (Index == gPciRootHpcCount) {
+      return EFI_SUCCESS;
+    }
+
+    //
+    // Stall for 30 microseconds..
+    //
+    gBS->Stall (30);
+
+    Delay--;
+
+  } while (Delay > 0);
+
+  return EFI_TIMEOUT;
+}
+
+/**
+  Check whether PCI-PCI bridge has PCI Hot Plug capability register block.
+
+  @param PciIoDevice    A Pointer to the PCI-PCI bridge.
+
+  @retval TRUE    PCI device is HPC.
+  @retval FALSE   PCI device is not HPC.
+
+**/
+BOOLEAN
+IsSHPC (
+  IN PCI_IO_DEVICE                      *PciIoDevice
+  )
+{
+
+  EFI_STATUS  Status;
+  UINT8       Offset;
+
+  if (PciIoDevice == NULL) {
+    return FALSE;
+  }
+
+  Offset = 0;
+  Status = LocateCapabilityRegBlock (
+            PciIoDevice,
+            EFI_PCI_CAPABILITY_ID_SHPC,
+            &Offset,
+            NULL
+            );
+
+  //
+  // If the PCI-PCI bridge has the hot plug controller build-in,
+  // then return TRUE;
+  //
+  if (!EFI_ERROR (Status)) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  Check whether PciIoDevice supports PCIe hotplug.
+
+  This is equivalent to the following condition:
+  - the device is either a PCIe switch downstream port or a root port,
+  - and the device has the SlotImplemented bit set in its PCIe capability
+    register,
+  - and the device has the HotPlugCapable bit set in its slot capabilities
+    register.
+
+  @param[in] PciIoDevice  The device being checked.
+
+  @retval TRUE   PciIoDevice is a PCIe port that accepts a hot-plugged device.
+  @retval FALSE  Otherwise.
+
+**/
+BOOLEAN
+SupportsPcieHotplug (
+  IN PCI_IO_DEVICE                      *PciIoDevice
+  )
+{
+  UINT32                       Offset;
+  EFI_STATUS                   Status;
+  PCI_REG_PCIE_CAPABILITY      Capability;
+  PCI_REG_PCIE_SLOT_CAPABILITY SlotCapability;
+
+  if (PciIoDevice == NULL) {
+    return FALSE;
+  }
+
+  //
+  // Read the PCI Express Capabilities Register
+  //
+  if (!PciIoDevice->IsPciExp) {
+    return FALSE;
+  }
+  Offset = PciIoDevice->PciExpressCapabilityOffset +
+           OFFSET_OF (PCI_CAPABILITY_PCIEXP, Capability);
+  Status = PciIoDevice->PciIo.Pci.Read (
+                                    &PciIoDevice->PciIo,
+                                    EfiPciIoWidthUint16,
+                                    Offset,
+                                    1,
+                                    &Capability
+                                    );
+  if (EFI_ERROR (Status)) {
+    return FALSE;
+  }
+
+  //
+  // Check the contents of the register
+  //
+  switch (Capability.Bits.DevicePortType) {
+  case PCIE_DEVICE_PORT_TYPE_ROOT_PORT:
+  case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT:
+    break;
+  default:
+    return FALSE;
+  }
+  if (!Capability.Bits.SlotImplemented) {
+    return FALSE;
+  }
+
+  //
+  // Read the Slot Capabilities Register
+  //
+  Offset = PciIoDevice->PciExpressCapabilityOffset +
+           OFFSET_OF (PCI_CAPABILITY_PCIEXP, SlotCapability);
+  Status = PciIoDevice->PciIo.Pci.Read (
+                                    &PciIoDevice->PciIo,
+                                    EfiPciIoWidthUint32,
+                                    Offset,
+                                    1,
+                                    &SlotCapability
+                                    );
+  if (EFI_ERROR (Status)) {
+    return FALSE;
+  }
+
+  //
+  // Check the contents of the register
+  //
+  if (SlotCapability.Bits.HotPlugCapable) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+  Get resource padding if the specified PCI bridge is a hot plug bus.
+
+  @param PciIoDevice    PCI bridge instance.
+
+**/
+VOID
+GetResourcePaddingForHpb (
+  IN PCI_IO_DEVICE      *PciIoDevice
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_HPC_STATE                     State;
+  UINT64                            PciAddress;
+  EFI_HPC_PADDING_ATTRIBUTES        Attributes;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+
+  if (IsPciHotPlugBus (PciIoDevice)) {
+    //
+    // If PCI-PCI bridge device is PCI Hot Plug bus.
+    //
+    PciAddress = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);
+    Status = gPciHotPlugInit->GetResourcePadding (
+                                gPciHotPlugInit,
+                                PciIoDevice->DevicePath,
+                                PciAddress,
+                                &State,
+                                (VOID **) &Descriptors,
+                                &Attributes
+                                );
+
+    if (EFI_ERROR (Status)) {
+      return;
+    }
+
+    if ((State & EFI_HPC_STATE_ENABLED) != 0 && (State & EFI_HPC_STATE_INITIALIZED) != 0) {
+      PciIoDevice->ResourcePaddingDescriptors = Descriptors;
+      PciIoDevice->PaddingAttributes          = Attributes;
+    }
+
+    return;
+  }
+}
+
+/**
+  Test whether PCI device is hot plug bus.
+
+  @param PciIoDevice  PCI device instance.
+
+  @retval TRUE    PCI device is a hot plug bus.
+  @retval FALSE   PCI device is not a hot plug bus.
+
+**/
+BOOLEAN
+IsPciHotPlugBus (
+  PCI_IO_DEVICE                       *PciIoDevice
+  )
+{
+  if (IsSHPC (PciIoDevice)) {
+    //
+    // If the PPB has the hot plug controller build-in,
+    // then return TRUE;
+    //
+    return TRUE;
+  }
+
+  if (SupportsPcieHotplug (PciIoDevice)) {
+    //
+    // If the PPB is a PCIe root complex port or a switch downstream port, and
+    // implements a hot-plug capable slot, then also return TRUE.
+    //
+    return TRUE;
+  }
+
+  //
+  // Otherwise, see if it is a Root HPC
+  //
+  if(IsRootPciHotPlugBus (PciIoDevice->DevicePath, NULL)) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h
new file mode 100644
index 0000000000..0b69237a3d
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h
@@ -0,0 +1,205 @@
+/** @file
+  PCI Hot Plug support functions declaration for PCI Bus module.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_PCI_HOT_PLUG_SUPPORT_H_
+#define _EFI_PCI_HOT_PLUG_SUPPORT_H_
+
+//
+// stall 1 second, its unit is 100ns
+//
+#define STALL_1_SECOND        1000000
+
+//
+// PCI Hot Plug controller private data
+//
+typedef struct {
+  EFI_EVENT Event;
+  BOOLEAN   Found;
+  BOOLEAN   Initialized;
+  VOID      *Padding;
+} ROOT_HPC_DATA;
+
+//
+// Reference of some global variables
+//
+extern EFI_PCI_HOT_PLUG_INIT_PROTOCOL *gPciHotPlugInit;
+extern EFI_HPC_LOCATION               *gPciRootHpcPool;
+extern ROOT_HPC_DATA                  *gPciRootHpcData;
+
+/**
+  Event notification function to set Hot Plug controller status.
+
+  @param  Event                    The event that invoke this function.
+  @param  Context                  The calling context, pointer to ROOT_HPC_DATA.
+
+**/
+VOID
+EFIAPI
+PciHPCInitialized (
+  IN EFI_EVENT    Event,
+  IN VOID         *Context
+  );
+
+/**
+  Compare two device paths to check if they are exactly same.
+
+  @param DevicePath1    A pointer to the first device path data structure.
+  @param DevicePath2    A pointer to the second device path data structure.
+
+  @retval TRUE    They are same.
+  @retval FALSE   They are not same.
+
+**/
+BOOLEAN
+EfiCompareDevicePath (
+  IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
+  IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
+  );
+
+/**
+  Check hot plug support and initialize root hot plug private data.
+
+  If Hot Plug is supported by the platform, call PCI Hot Plug Init protocol
+  to get PCI Hot Plug controller's information and constructor the root hot plug
+  private data structure.
+
+  @retval EFI_SUCCESS           They are same.
+  @retval EFI_UNSUPPORTED       No PCI Hot Plug controller on the platform.
+  @retval EFI_OUT_OF_RESOURCES  No memory to constructor root hot plug private
+                                data structure.
+
+**/
+EFI_STATUS
+InitializeHotPlugSupport (
+  VOID
+  );
+
+/**
+  Test whether PCI device is hot plug bus.
+
+  @param PciIoDevice  PCI device instance.
+
+  @retval TRUE    PCI device is a hot plug bus.
+  @retval FALSE   PCI device is not a hot plug bus.
+
+**/
+BOOLEAN
+IsPciHotPlugBus (
+  PCI_IO_DEVICE                       *PciIoDevice
+  );
+
+/**
+  Test whether device path is for root pci hot plug bus.
+
+  @param HpbDevicePath  A pointer to device path data structure to be tested.
+  @param HpIndex        If HpIndex is not NULL, return the index of root hot
+                        plug in global array when TRUE is returned.
+
+  @retval TRUE          The device path is for root pci hot plug bus.
+  @retval FALSE         The device path is not for root pci hot plug bus.
+
+**/
+BOOLEAN
+IsRootPciHotPlugBus (
+  IN  EFI_DEVICE_PATH_PROTOCOL        *HpbDevicePath,
+  OUT UINTN                           *HpIndex    OPTIONAL
+  );
+
+/**
+  Test whether device path is for root pci hot plug controller.
+
+  @param HpcDevicePath  A pointer to device path data structure to be tested.
+  @param HpIndex        If HpIndex is not NULL, return the index of root hot
+                        plug in global array when TRUE is returned.
+
+  @retval TRUE          The device path is for root pci hot plug controller.
+  @retval FALSE         The device path is not for root pci hot plug controller.
+
+**/
+BOOLEAN
+IsRootPciHotPlugController (
+  IN EFI_DEVICE_PATH_PROTOCOL         *HpcDevicePath,
+  OUT UINTN                           *HpIndex
+  );
+
+/**
+  Creating event object for PCI Hot Plug controller.
+
+  @param  HpIndex   Index of hot plug device in global array.
+  @param  Event     The returned event that invoke this function.
+
+  @return Status of create event.
+
+**/
+EFI_STATUS
+CreateEventForHpc (
+  IN  UINTN      HpIndex,
+  OUT EFI_EVENT  *Event
+  );
+
+/**
+  Wait for all root PCI Hot Plug controller finished initializing.
+
+  @param TimeoutInMicroSeconds  Microseconds to wait for all root HPCs' initialization.
+
+  @retval EFI_SUCCESS           All HPCs initialization finished.
+  @retval EFI_TIMEOUT           Not ALL HPCs initialization finished in Microseconds.
+
+**/
+EFI_STATUS
+AllRootHPCInitialized (
+  IN  UINTN           TimeoutInMicroSeconds
+  );
+
+/**
+  Check whether PCI-PCI bridge has PCI Hot Plug capability register block.
+
+  @param PciIoDevice    A Pointer to the PCI-PCI bridge.
+
+  @retval TRUE    PCI device is HPC.
+  @retval FALSE   PCI device is not HPC.
+
+**/
+BOOLEAN
+IsSHPC (
+  IN PCI_IO_DEVICE                      *PciIoDevice
+  );
+
+/**
+  Check whether PciIoDevice supports PCIe hotplug.
+
+  This is equivalent to the following condition:
+  - the device is either a PCIe switch downstream port or a root port,
+  - and the device has the SlotImplemented bit set in its PCIe capability
+    register,
+  - and the device has the HotPlugCapable bit set in its slot capabilities
+    register.
+
+  @param[in] PciIoDevice  The device being checked.
+
+  @retval TRUE   PciIoDevice is a PCIe port that accepts a hot-plugged device.
+  @retval FALSE  Otherwise.
+
+**/
+BOOLEAN
+SupportsPcieHotplug (
+  IN PCI_IO_DEVICE                      *PciIoDevice
+  );
+
+/**
+  Get resource padding if the specified PCI bridge is a hot plug bus.
+
+  @param PciIoDevice    PCI bridge instance.
+
+**/
+VOID
+GetResourcePaddingForHpb (
+  IN PCI_IO_DEVICE      *PciIoDevice
+  );
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c
new file mode 100644
index 0000000000..c656056315
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c
@@ -0,0 +1,2087 @@
+/** @file
+  EFI PCI IO protocol functions implementation for PCI Bus module.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+
+extern EDKII_IOMMU_PROTOCOL                          *mIoMmuProtocol;
+
+//
+// Pci Io Protocol Interface
+//
+EFI_PCI_IO_PROTOCOL  mPciIoInterface = {
+  PciIoPollMem,
+  PciIoPollIo,
+  {
+    PciIoMemRead,
+    PciIoMemWrite
+  },
+  {
+    PciIoIoRead,
+    PciIoIoWrite
+  },
+  {
+    PciIoConfigRead,
+    PciIoConfigWrite
+  },
+  PciIoCopyMem,
+  PciIoMap,
+  PciIoUnmap,
+  PciIoAllocateBuffer,
+  PciIoFreeBuffer,
+  PciIoFlush,
+  PciIoGetLocation,
+  PciIoAttributes,
+  PciIoGetBarAttributes,
+  PciIoSetBarAttributes,
+  0,
+  NULL
+};
+
+/**
+  Initializes a PCI I/O Instance.
+
+  @param PciIoDevice    Pci device instance.
+
+**/
+VOID
+InitializePciIoInstance (
+  IN PCI_IO_DEVICE               *PciIoDevice
+  )
+{
+  CopyMem (&PciIoDevice->PciIo, &mPciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));
+}
+
+/**
+  Verifies access to a PCI Base Address Register (BAR).
+
+  @param PciIoDevice  Pci device instance.
+  @param BarIndex     The BAR index of the standard PCI Configuration header to use as the
+                      base address for the memory or I/O operation to perform.
+  @param Type         Operation type could be memory or I/O.
+  @param Width        Signifies the width of the memory or I/O operations.
+  @param Count        The number of memory or I/O operations to perform.
+  @param Offset       The offset within the PCI configuration space for the PCI controller.
+
+  @retval EFI_INVALID_PARAMETER Invalid Width/BarIndex or Bar type.
+  @retval EFI_SUCCESS           Successfully verified.
+
+**/
+EFI_STATUS
+PciIoVerifyBarAccess (
+  IN PCI_IO_DEVICE                   *PciIoDevice,
+  IN UINT8                           BarIndex,
+  IN PCI_BAR_TYPE                    Type,
+  IN IN EFI_PCI_IO_PROTOCOL_WIDTH    Width,
+  IN IN UINTN                        Count,
+  IN UINT64                          *Offset
+  )
+{
+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // BarIndex 0-5 is legal
+  //
+  if (BarIndex >= PCI_MAX_BAR) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!CheckBarType (PciIoDevice, BarIndex, Type)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX
+  // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
+  //
+  if (Width >= EfiPciIoWidthFifoUint8 && Width <= EfiPciIoWidthFifoUint64) {
+    Count = 1;
+  }
+
+  Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);
+
+  if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Verifies access to a PCI Configuration Header.
+
+  @param PciIoDevice  Pci device instance.
+  @param Width        Signifies the width of the memory or I/O operations.
+  @param Count        The number of memory or I/O operations to perform.
+  @param Offset       The offset within the PCI configuration space for the PCI controller.
+
+  @retval EFI_INVALID_PARAMETER  Invalid Width
+  @retval EFI_UNSUPPORTED        Offset overflowed.
+  @retval EFI_SUCCESS            Successfully verified.
+
+**/
+EFI_STATUS
+PciIoVerifyConfigAccess (
+  IN PCI_IO_DEVICE              *PciIoDevice,
+  IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN UINTN                      Count,
+  IN UINT64                     *Offset
+  )
+{
+  UINT64  ExtendOffset;
+
+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
+  //
+  Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);
+
+  if (PciIoDevice->IsPciExp) {
+    if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) {
+      return EFI_UNSUPPORTED;
+    }
+
+    ExtendOffset  = LShiftU64 (*Offset, 32);
+    *Offset       = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);
+    *Offset       = (*Offset) | ExtendOffset;
+
+  } else {
+    if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) {
+      return EFI_UNSUPPORTED;
+    }
+
+    *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is
+  satisfied or after a defined duration.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory or I/O operations.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for the memory operation to perform.
+  @param  Offset                The offset within the selected BAR to start the memory operation.
+  @param  Mask                  Mask used for the polling criteria.
+  @param  Value                 The comparison value used for the polling exit criteria.
+  @param  Delay                 The number of 100 ns units to poll.
+  @param  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_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       Offset is not valid for the BarIndex of this PCI controller.
+  @retval EFI_TIMEOUT           Delay expired before a match occurred.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoPollMem (
+  IN  EFI_PCI_IO_PROTOCOL        *This,
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT8                      BarIndex,
+  IN  UINT64                     Offset,
+  IN  UINT64                     Mask,
+  IN  UINT64                     Value,
+  IN  UINT64                     Delay,
+  OUT UINT64                     *Result
+  )
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (Width > EfiPciIoWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
+  //
+  if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
+    if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
+      Status  = PciIoMemRead (This, Width, BarIndex, Offset, 1, Result);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+      if ((*Result & Mask) == Value || Delay == 0) {
+        return EFI_SUCCESS;
+      }
+      do {
+        //
+        // Stall 10 us = 100 * 100ns
+        //
+        gBS->Stall (10);
+
+        Status  = PciIoMemRead (This, Width, BarIndex, Offset, 1, Result);
+        if (EFI_ERROR (Status)) {
+          return Status;
+        }
+        if ((*Result & Mask) == Value) {
+          return EFI_SUCCESS;
+        }
+        if (Delay <= 100) {
+          return EFI_TIMEOUT;
+        }
+        Delay -= 100;
+      } while (TRUE);
+    }
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->PollMem (
+                                           PciIoDevice->PciRootBridgeIo,
+                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                           Offset,
+                                           Mask,
+                                           Value,
+                                           Delay,
+                                           Result
+                                           );
+
+  if (EFI_ERROR (Status)) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
+      PciIoDevice->DevicePath
+      );
+  }
+
+  return Status;
+}
+
+/**
+  Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is
+  satisfied or after a defined duration.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory or I/O operations.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for the memory operation to perform.
+  @param  Offset                The offset within the selected BAR to start the memory operation.
+  @param  Mask                  Mask used for the polling criteria.
+  @param  Value                 The comparison value used for the polling exit criteria.
+  @param  Delay                 The number of 100 ns units to poll.
+  @param  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_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       Offset is not valid for the BarIndex of this PCI controller.
+  @retval EFI_TIMEOUT           Delay expired before a match occurred.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoPollIo (
+  IN  EFI_PCI_IO_PROTOCOL        *This,
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT8                      BarIndex,
+  IN  UINT64                     Offset,
+  IN  UINT64                     Mask,
+  IN  UINT64                     Value,
+  IN  UINT64                     Delay,
+  OUT UINT64                     *Result
+  )
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if ((UINT32)Width > EfiPciIoWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
+  //
+  if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
+    if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
+      Status  = PciIoIoRead (This, Width, BarIndex, Offset, 1, Result);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+      if ((*Result & Mask) == Value || Delay == 0) {
+        return EFI_SUCCESS;
+      }
+      do {
+        //
+        // Stall 10 us = 100 * 100ns
+        //
+        gBS->Stall (10);
+
+        Status  = PciIoIoRead (This, Width, BarIndex, Offset, 1, Result);
+        if (EFI_ERROR (Status)) {
+          return Status;
+        }
+        if ((*Result & Mask) == Value) {
+          return EFI_SUCCESS;
+        }
+        if (Delay <= 100) {
+          return EFI_TIMEOUT;
+        }
+        Delay -= 100;
+      } while (TRUE);
+    }
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->PollIo (
+                                           PciIoDevice->PciRootBridgeIo,
+                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                           Offset,
+                                           Mask,
+                                           Value,
+                                           Delay,
+                                           Result
+                                           );
+
+  if (EFI_ERROR (Status)) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
+      PciIoDevice->DevicePath
+      );
+  }
+
+  return Status;
+}
+
+/**
+  Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory or I/O operations.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for the memory or I/O operation to perform.
+  @param  Offset                The offset within the selected BAR to start the memory or I/O operation.
+  @param  Count                 The number of memory or I/O operations to perform.
+  @param  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 controller.
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI BAR specified by BarIndex.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoMemRead (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT8                      BarIndex,
+  IN     UINT64                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  )
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
+  //
+  if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
+    if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
+      Count *=  (UINTN)(1 << (Width & 0x03));
+      Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03));
+    }
+  }
+
+
+  Status = PciIoDevice->PciRootBridgeIo->Mem.Read (
+                                              PciIoDevice->PciRootBridgeIo,
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                              Offset,
+                                              Count,
+                                              Buffer
+                                              );
+
+  if (EFI_ERROR (Status)) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR,
+      PciIoDevice->DevicePath
+      );
+  }
+
+  return Status;
+}
+
+/**
+  Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory or I/O operations.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for the memory or I/O operation to perform.
+  @param  Offset                The offset within the selected BAR to start the memory or I/O operation.
+  @param  Count                 The number of memory or I/O operations to perform.
+  @param  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 controller.
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI BAR specified by BarIndex.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoMemWrite (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT8                      BarIndex,
+  IN     UINT64                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  )
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
+  //
+  if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
+    if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
+      Count *=  (UINTN)(1 << (Width & 0x03));
+      Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03));
+    }
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->Mem.Write (
+                                              PciIoDevice->PciRootBridgeIo,
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                              Offset,
+                                              Count,
+                                              Buffer
+                                              );
+
+  if (EFI_ERROR (Status)) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR,
+      PciIoDevice->DevicePath
+      );
+  }
+
+  return Status;
+}
+
+/**
+  Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory or I/O operations.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for the memory or I/O operation to perform.
+  @param  Offset                The offset within the selected BAR to start the memory or I/O operation.
+  @param  Count                 The number of memory or I/O operations to perform.
+  @param  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 controller.
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI BAR specified by BarIndex.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoIoRead (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT8                      BarIndex,
+  IN     UINT64                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  )
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
+  //
+  if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
+    if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
+      Count *=  (UINTN)(1 << (Width & 0x03));
+      Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03));
+    }
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->Io.Read (
+                                              PciIoDevice->PciRootBridgeIo,
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                              Offset,
+                                              Count,
+                                              Buffer
+                                              );
+
+  if (EFI_ERROR (Status)) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR,
+      PciIoDevice->DevicePath
+      );
+  }
+
+  return Status;
+}
+
+/**
+  Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory or I/O operations.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for the memory or I/O operation to perform.
+  @param  Offset                The offset within the selected BAR to start the memory or I/O operation.
+  @param  Count                 The number of memory or I/O operations to perform.
+  @param  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 controller.
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI BAR specified by BarIndex.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoIoWrite (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT8                      BarIndex,
+  IN     UINT64                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  )
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
+  //
+  if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
+    if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
+      Count *=  (UINTN)(1 << (Width & 0x03));
+      Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03));
+    }
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->Io.Write (
+                                              PciIoDevice->PciRootBridgeIo,
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                              Offset,
+                                              Count,
+                                              Buffer
+                                              );
+
+  if (EFI_ERROR (Status)) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR,
+      PciIoDevice->DevicePath
+      );
+  }
+
+  return Status;
+}
+
+/**
+  Enable a PCI driver to access PCI controller registers in PCI configuration space.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory operations.
+  @param  Offset                The offset within the PCI configuration space for the PCI controller.
+  @param  Count                 The number of PCI configuration operations to perform.
+  @param  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 controller.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI configuration header of the PCI controller.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoConfigRead (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT32                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  )
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+  UINT64        Address;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  Address     = Offset;
+  Status      = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
+  //
+  if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
+    if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
+      Count *=  (UINTN)(1 << (Width & 0x03));
+      Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03));
+    }
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->Pci.Read (
+                                               PciIoDevice->PciRootBridgeIo,
+                                               (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                               Address,
+                                               Count,
+                                               Buffer
+                                               );
+
+  if (EFI_ERROR (Status)) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR,
+      PciIoDevice->DevicePath
+      );
+  }
+
+  return Status;
+}
+
+/**
+  Enable a PCI driver to access PCI controller registers in PCI configuration space.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory operations.
+  @param  Offset                The offset within the PCI configuration space for the PCI controller.
+  @param  Count                 The number of PCI configuration operations to perform.
+  @param  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 controller.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI configuration header of the PCI controller.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoConfigWrite (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT32                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  )
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+  UINT64        Address;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  Address     = Offset;
+  Status      = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
+  //
+  if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
+    if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
+      Count *=  (UINTN)(1 << (Width & 0x03));
+      Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03));
+    }
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->Pci.Write (
+                                              PciIoDevice->PciRootBridgeIo,
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                              Address,
+                                              Count,
+                                              Buffer
+                                              );
+
+  if (EFI_ERROR (Status)) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR,
+      PciIoDevice->DevicePath
+      );
+  }
+
+  return Status;
+}
+
+/**
+  Enables a PCI driver to copy one region of PCI memory space to another region of PCI
+  memory space.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory operations.
+  @param  DestBarIndex          The BAR index in the standard PCI Configuration header to use as the
+                                base address for the memory operation to perform.
+  @param  DestOffset            The destination offset within the BAR specified by DestBarIndex to
+                                start the memory writes for the copy operation.
+  @param  SrcBarIndex           The BAR index in the standard PCI Configuration header to use as the
+                                base address for the memory operation to perform.
+  @param  SrcOffset             The source offset within the BAR specified by SrcBarIndex to start
+                                the memory reads for the copy operation.
+  @param  Count                 The number of memory operations to perform. Bytes moved is Width
+                                size * Count, starting at DestOffset and SrcOffset.
+
+  @retval EFI_SUCCESS           The data was copied from one memory region to another memory region.
+  @retval EFI_UNSUPPORTED       DestBarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       SrcBarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       The address range specified by DestOffset, Width, and Count
+                                is not valid for the PCI BAR specified by DestBarIndex.
+  @retval EFI_UNSUPPORTED       The address range specified by SrcOffset, Width, and Count is
+                                not valid for the PCI BAR specified by SrcBarIndex.
+  @retval EFI_INVALID_PARAMETER Width is invalid.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoCopyMem (
+  IN EFI_PCI_IO_PROTOCOL              *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,
+  IN     UINT8                        DestBarIndex,
+  IN     UINT64                       DestOffset,
+  IN     UINT8                        SrcBarIndex,
+  IN     UINT64                       SrcOffset,
+  IN     UINTN                        Count
+  )
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Width == EfiPciIoWidthFifoUint8  ||
+      Width == EfiPciIoWidthFifoUint16 ||
+      Width == EfiPciIoWidthFifoUint32 ||
+      Width == EfiPciIoWidthFifoUint64 ||
+      Width == EfiPciIoWidthFillUint8  ||
+      Width == EfiPciIoWidthFillUint16 ||
+      Width == EfiPciIoWidthFillUint32 ||
+      Width == EfiPciIoWidthFillUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset);
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
+  //
+  if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
+    if ((SrcOffset & ((1 << (Width & 0x03)) - 1)) != 0 || (DestOffset & ((1 << (Width & 0x03)) - 1)) != 0) {
+      Count *=  (UINTN)(1 << (Width & 0x03));
+      Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03));
+    }
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->CopyMem (
+                                          PciIoDevice->PciRootBridgeIo,
+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+                                          DestOffset,
+                                          SrcOffset,
+                                          Count
+                                          );
+
+  if (EFI_ERROR (Status)) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
+      PciIoDevice->DevicePath
+      );
+  }
+
+  return Status;
+}
+
+/**
+  Provides the PCI controller-specific addresses needed to access system memory.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Operation             Indicates if the bus master is going to read or write to system memory.
+  @param  HostAddress           The system memory address to map to the PCI controller.
+  @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes
+                                that were mapped.
+  @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to
+                                access the hosts HostAddress.
+  @param  Mapping               A resulting value to pass to Unmap().
+
+  @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.
+  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoMap (
+  IN     EFI_PCI_IO_PROTOCOL            *This,
+  IN     EFI_PCI_IO_PROTOCOL_OPERATION  Operation,
+  IN     VOID                           *HostAddress,
+  IN OUT UINTN                          *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,
+  OUT    VOID                           **Mapping
+  )
+{
+  EFI_STATUS                                 Status;
+  PCI_IO_DEVICE                              *PciIoDevice;
+  UINT64                                     IoMmuAttribute;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  RootBridgeIoOperation;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if ((UINT32)Operation >= EfiPciIoOperationMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RootBridgeIoOperation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)Operation;
+  if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {
+    RootBridgeIoOperation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)(Operation + EfiPciOperationBusMasterRead64);
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->Map (
+                                          PciIoDevice->PciRootBridgeIo,
+                                          RootBridgeIoOperation,
+                                          HostAddress,
+                                          NumberOfBytes,
+                                          DeviceAddress,
+                                          Mapping
+                                          );
+
+  if (EFI_ERROR (Status)) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
+      PciIoDevice->DevicePath
+      );
+  }
+
+  if (mIoMmuProtocol != NULL) {
+    if (!EFI_ERROR (Status)) {
+      switch (Operation) {
+      case EfiPciIoOperationBusMasterRead:
+        IoMmuAttribute = EDKII_IOMMU_ACCESS_READ;
+        break;
+      case EfiPciIoOperationBusMasterWrite:
+        IoMmuAttribute = EDKII_IOMMU_ACCESS_WRITE;
+        break;
+      case EfiPciIoOperationBusMasterCommonBuffer:
+        IoMmuAttribute = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE;
+        break;
+      default:
+        ASSERT(FALSE);
+        return EFI_INVALID_PARAMETER;
+      }
+      mIoMmuProtocol->SetAttribute (
+                        mIoMmuProtocol,
+                        PciIoDevice->Handle,
+                        *Mapping,
+                        IoMmuAttribute
+                        );
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Completes the Map() operation and releases any corresponding resources.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Mapping               The mapping value returned from Map().
+
+  @retval EFI_SUCCESS           The range was unmapped.
+  @retval EFI_DEVICE_ERROR      The data was not committed to the target system memory.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoUnmap (
+  IN  EFI_PCI_IO_PROTOCOL  *This,
+  IN  VOID                 *Mapping
+  )
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if (mIoMmuProtocol != NULL) {
+    mIoMmuProtocol->SetAttribute (
+                      mIoMmuProtocol,
+                      PciIoDevice->Handle,
+                      Mapping,
+                      0
+                      );
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->Unmap (
+                                          PciIoDevice->PciRootBridgeIo,
+                                          Mapping
+                                          );
+
+  if (EFI_ERROR (Status)) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
+      PciIoDevice->DevicePath
+      );
+  }
+
+  return Status;
+}
+
+/**
+  Allocates pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer
+  or EfiPciOperationBusMasterCommonBuffer64 mapping.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @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.
+
+  @retval EFI_SUCCESS           The requested memory pages were allocated.
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are
+                                MEMORY_WRITE_COMBINE, MEMORY_CACHED and DUAL_ADDRESS_CYCLE.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoAllocateBuffer (
+  IN  EFI_PCI_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;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  if ((Attributes &
+      (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) != 0){
+    return EFI_UNSUPPORTED;
+  }
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {
+    Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
+  }
+
+  Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (
+                                          PciIoDevice->PciRootBridgeIo,
+                                          Type,
+                                          MemoryType,
+                                          Pages,
+                                          HostAddress,
+                                          Attributes
+                                          );
+
+  if (EFI_ERROR (Status)) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
+      PciIoDevice->DevicePath
+      );
+  }
+
+  return Status;
+}
+
+/**
+  Frees memory that was allocated with AllocateBuffer().
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @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
+PciIoFreeBuffer (
+  IN  EFI_PCI_IO_PROTOCOL   *This,
+  IN  UINTN                 Pages,
+  IN  VOID                  *HostAddress
+  )
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (
+                                          PciIoDevice->PciRootBridgeIo,
+                                          Pages,
+                                          HostAddress
+                                          );
+
+  if (EFI_ERROR (Status)) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
+      PciIoDevice->DevicePath
+      );
+  }
+
+  return Status;
+}
+
+/**
+  Flushes all PCI posted write transactions from a PCI host bridge to system memory.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+
+  @retval EFI_SUCCESS           The PCI posted write transactions were flushed from the PCI host
+                                bridge to system memory.
+  @retval EFI_DEVICE_ERROR      The PCI posted write transactions were not flushed from the PCI
+                                host bridge due to a hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoFlush (
+  IN  EFI_PCI_IO_PROTOCOL  *This
+  )
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  Status = PciIoDevice->PciRootBridgeIo->Flush (
+                                           PciIoDevice->PciRootBridgeIo
+                                           );
+  if (EFI_ERROR (Status)) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
+      PciIoDevice->DevicePath
+      );
+  }
+
+  return Status;
+}
+
+/**
+  Retrieves this PCI controller's current PCI bus number, device number, and function number.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  SegmentNumber         The PCI controller's current PCI segment number.
+  @param  BusNumber             The PCI controller's current PCI bus number.
+  @param  DeviceNumber          The PCI controller's current PCI device number.
+  @param  FunctionNumber        The PCI controller's current PCI function number.
+
+  @retval EFI_SUCCESS           The PCI controller location was returned.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoGetLocation (
+  IN  EFI_PCI_IO_PROTOCOL  *This,
+  OUT UINTN                *Segment,
+  OUT UINTN                *Bus,
+  OUT UINTN                *Device,
+  OUT UINTN                *Function
+  )
+{
+  PCI_IO_DEVICE *PciIoDevice;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Segment  = PciIoDevice->PciRootBridgeIo->SegmentNumber;
+  *Bus      = PciIoDevice->BusNumber;
+  *Device   = PciIoDevice->DeviceNumber;
+  *Function = PciIoDevice->FunctionNumber;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Check BAR type for PCI resource.
+
+  @param PciIoDevice   PCI device instance.
+  @param BarIndex      The BAR index of the standard PCI Configuration header to use as the
+                       base address for the memory or I/O operation to perform.
+  @param BarType       Memory or I/O.
+
+  @retval TRUE         Pci device's bar type is same with input BarType.
+  @retval TRUE         Pci device's bar type is not same with input BarType.
+
+**/
+BOOLEAN
+CheckBarType (
+  IN PCI_IO_DEVICE          *PciIoDevice,
+  IN UINT8                  BarIndex,
+  IN PCI_BAR_TYPE           BarType
+  )
+{
+  switch (BarType) {
+
+  case PciBarTypeMem:
+
+    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32  &&
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 &&
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 &&
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64    ) {
+      return FALSE;
+    }
+
+    return TRUE;
+
+  case PciBarTypeIo:
+    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 &&
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){
+      return FALSE;
+    }
+
+    return TRUE;
+
+  default:
+    break;
+  }
+
+  return FALSE;
+}
+
+/**
+  Set/Disable new attributes to a Root Bridge.
+
+  @param  PciIoDevice  Pci device instance.
+  @param  Attributes   New attribute want to be set.
+  @param  Operation    Set or Disable.
+
+  @retval  EFI_UNSUPPORTED  If root bridge does not support change attribute.
+  @retval  EFI_SUCCESS      Successfully set new attributes.
+
+**/
+EFI_STATUS
+ModifyRootBridgeAttributes (
+  IN  PCI_IO_DEVICE                            *PciIoDevice,
+  IN  UINT64                                   Attributes,
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation
+  )
+{
+  UINT64      PciRootBridgeSupports;
+  UINT64      PciRootBridgeAttributes;
+  UINT64      NewPciRootBridgeAttributes;
+  EFI_STATUS  Status;
+
+  //
+  // Get the current attributes of this PCI device's PCI Root Bridge
+  //
+  Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
+                                          PciIoDevice->PciRootBridgeIo,
+                                          &PciRootBridgeSupports,
+                                          &PciRootBridgeAttributes
+                                          );
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Mask off attributes not supported by PCI root bridge.
+  //
+  Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |
+                          EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |
+                          EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE);
+
+  //
+  // Record the new attribute of the Root Bridge
+  //
+  if (Operation == EfiPciIoAttributeOperationEnable) {
+    NewPciRootBridgeAttributes = PciRootBridgeAttributes | Attributes;
+  } else {
+    NewPciRootBridgeAttributes = PciRootBridgeAttributes & (~Attributes);
+  }
+
+  //
+  // Call the PCI Root Bridge to attempt to modify the attributes
+  //
+  if ((NewPciRootBridgeAttributes ^ PciRootBridgeAttributes) != 0) {
+
+    Status = PciIoDevice->PciRootBridgeIo->SetAttributes (
+                                            PciIoDevice->PciRootBridgeIo,
+                                            NewPciRootBridgeAttributes,
+                                            NULL,
+                                            NULL
+                                            );
+    if (EFI_ERROR (Status)) {
+      //
+      // The PCI Root Bridge could not modify the attributes, so return the error.
+      //
+      return EFI_UNSUPPORTED;
+    }
+  }
+
+  //
+  // Also update the attributes for this Root Bridge structure
+  //
+  PciIoDevice->Attributes = NewPciRootBridgeAttributes;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Check whether this device can be enable/disable to snoop.
+
+  @param PciIoDevice  Pci device instance.
+  @param Operation    Enable/Disable.
+
+  @retval EFI_UNSUPPORTED  Pci device is not GFX device or not support snoop.
+  @retval EFI_SUCCESS      Snoop can be supported.
+
+**/
+EFI_STATUS
+SupportPaletteSnoopAttributes (
+  IN PCI_IO_DEVICE                            *PciIoDevice,
+  IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation
+  )
+{
+  PCI_IO_DEVICE *Temp;
+  UINT16        VGACommand;
+
+  //
+  // Snoop attribute can be only modified by GFX
+  //
+  if (!IS_PCI_GFX (&PciIoDevice->Pci)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Get the boot VGA on the same Host Bridge
+  //
+  Temp = LocateVgaDeviceOnHostBridge (PciIoDevice->PciRootBridgeIo->ParentHandle);
+
+  if (Temp == NULL) {
+    //
+    // If there is no VGA device on the segment, set
+    // this graphics card to decode the palette range
+    //
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Check these two agents are on the same path
+  //
+  if (!PciDevicesOnTheSamePath (Temp, PciIoDevice)) {
+    //
+    // they are not on the same path, so snoop can be enabled or disabled
+    //
+    return EFI_SUCCESS;
+  }
+  //
+  // Check if they are on the same bus
+  //
+  if (Temp->Parent == PciIoDevice->Parent) {
+
+    PCI_READ_COMMAND_REGISTER (Temp, &VGACommand);
+
+    //
+    // If they are on the same bus, either one can
+    // be set to snoop, the other set to decode
+    //
+    if ((VGACommand & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {
+      //
+      // VGA has set to snoop, so GFX can be only set to disable snoop
+      //
+      if (Operation == EfiPciIoAttributeOperationEnable) {
+        return EFI_UNSUPPORTED;
+      }
+    } else {
+      //
+      // VGA has disabled to snoop, so GFX can be only enabled
+      //
+      if (Operation == EfiPciIoAttributeOperationDisable) {
+        return EFI_UNSUPPORTED;
+      }
+    }
+
+    return EFI_SUCCESS;
+  }
+
+  //
+  // If they are on  the same path but on the different bus
+  // The first agent is set to snoop, the second one set to
+  // decode
+  //
+
+  if (Temp->BusNumber < PciIoDevice->BusNumber) {
+    //
+    // GFX should be set to decode
+    //
+    if (Operation == EfiPciIoAttributeOperationDisable) {
+      PCI_ENABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
+      Temp->Attributes |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
+    } else {
+      return EFI_UNSUPPORTED;
+    }
+
+  } else {
+    //
+    // GFX should be set to snoop
+    //
+    if (Operation == EfiPciIoAttributeOperationEnable) {
+      PCI_DISABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
+      Temp->Attributes &= (~(UINT64)EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
+    } else {
+      return EFI_UNSUPPORTED;
+    }
+
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Performs an operation on the attributes that this PCI controller supports. The operations include
+  getting the set of supported attributes, retrieving the current attributes, setting the current
+  attributes, enabling attributes, and disabling attributes.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Operation             The operation to perform on the attributes for this PCI controller.
+  @param  Attributes            The mask of attributes that are used for Set, Enable, and Disable
+                                operations.
+  @param  Result                A pointer to the result mask of attributes that are returned for the Get
+                                and Supported operations.
+
+  @retval EFI_SUCCESS           The operation on the PCI controller's attributes was completed.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_UNSUPPORTED       one or more of the bits set in
+                                Attributes are not supported by this PCI controller or one of
+                                its parent bridges when Operation is Set, Enable or Disable.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoAttributes (
+  IN EFI_PCI_IO_PROTOCOL                       * This,
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,
+  IN  UINT64                                   Attributes,
+  OUT UINT64                                   *Result OPTIONAL
+  )
+{
+  EFI_STATUS    Status;
+
+  PCI_IO_DEVICE *PciIoDevice;
+  PCI_IO_DEVICE *UpStreamBridge;
+  PCI_IO_DEVICE *Temp;
+
+  UINT64        Supports;
+  UINT64        UpStreamAttributes;
+  UINT16        BridgeControl;
+  UINT16        Command;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  switch (Operation) {
+  case EfiPciIoAttributeOperationGet:
+    if (Result == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    *Result = PciIoDevice->Attributes;
+    return EFI_SUCCESS;
+
+  case EfiPciIoAttributeOperationSupported:
+    if (Result == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    *Result = PciIoDevice->Supports;
+    return EFI_SUCCESS;
+
+  case EfiPciIoAttributeOperationSet:
+    Status = PciIoDevice->PciIo.Attributes (
+                                  &(PciIoDevice->PciIo),
+                                  EfiPciIoAttributeOperationEnable,
+                                  Attributes,
+                                  NULL
+                                  );
+    if (EFI_ERROR (Status)) {
+      return EFI_UNSUPPORTED;
+    }
+
+    Status = PciIoDevice->PciIo.Attributes (
+                                  &(PciIoDevice->PciIo),
+                                  EfiPciIoAttributeOperationDisable,
+                                  (~Attributes) & (PciIoDevice->Supports),
+                                  NULL
+                                  );
+    if (EFI_ERROR (Status)) {
+      return EFI_UNSUPPORTED;
+    }
+
+    return EFI_SUCCESS;
+
+  case EfiPciIoAttributeOperationEnable:
+  case EfiPciIoAttributeOperationDisable:
+    break;
+
+  default:
+    return EFI_INVALID_PARAMETER;
+  }
+  //
+  // Just a trick for ENABLE attribute
+  // EFI_PCI_DEVICE_ENABLE is not defined in UEFI spec, which is the internal usage.
+  // So, this logic doesn't conform to UEFI spec, which should be removed.
+  // But this trick logic is still kept for some binary drivers that depend on it.
+  //
+  if ((Attributes & EFI_PCI_DEVICE_ENABLE) == EFI_PCI_DEVICE_ENABLE) {
+    Attributes &= (PciIoDevice->Supports);
+
+    //
+    // Raise the EFI_P_PC_ENABLE Status code
+    //
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_PROGRESS_CODE,
+      EFI_IO_BUS_PCI | EFI_P_PC_ENABLE,
+      PciIoDevice->DevicePath
+      );
+  }
+
+  //
+  // Check VGA and VGA16, they can not be set at the same time
+  //
+  if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) != 0) {
+    if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) != 0) {
+      return EFI_UNSUPPORTED;
+    }
+  }
+
+  //
+  // If no attributes can be supported, then return.
+  // Otherwise, set the attributes that it can support.
+  //
+  Supports = (PciIoDevice->Supports) & Attributes;
+  if (Supports != Attributes) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // For Root Bridge, just call RootBridgeIo to set attributes;
+  //
+  if (PciIoDevice->Parent == NULL) {
+    Status = ModifyRootBridgeAttributes (PciIoDevice, Attributes, Operation);
+    return Status;
+  }
+
+  Command       = 0;
+  BridgeControl = 0;
+
+  //
+  // For PPB & P2C, set relevant attribute bits
+  //
+  if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+
+    if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) != 0) {
+      BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA;
+    }
+
+    if ((Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) != 0) {
+      BridgeControl |= EFI_PCI_BRIDGE_CONTROL_ISA;
+    }
+
+    if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) != 0) {
+      Command |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
+    }
+
+    if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) != 0) {
+      BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA_16;
+    }
+
+  } else {
+    //
+    // Do with the attributes on VGA
+    // Only for VGA's legacy resource, we just can enable once.
+    //
+    if ((Attributes &
+        (EFI_PCI_IO_ATTRIBUTE_VGA_IO    |
+         EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 |
+         EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY)) != 0) {
+      //
+      // Check if a VGA has been enabled before enabling a new one
+      //
+      if (Operation == EfiPciIoAttributeOperationEnable) {
+        //
+        // Check if there have been an active VGA device on the same Host Bridge
+        //
+        Temp = LocateVgaDeviceOnHostBridge (PciIoDevice->PciRootBridgeIo->ParentHandle);
+        if (Temp != NULL && Temp != PciIoDevice) {
+          //
+          // An active VGA has been detected, so can not enable another
+          //
+          return EFI_UNSUPPORTED;
+        }
+      }
+    }
+
+    //
+    // Do with the attributes on GFX
+    //
+    if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) != 0) {
+
+      if (Operation == EfiPciIoAttributeOperationEnable) {
+        //
+        // Check if snoop can be enabled in current configuration
+        //
+        Status = SupportPaletteSnoopAttributes (PciIoDevice, Operation);
+
+        if (EFI_ERROR (Status)) {
+
+          //
+          // Enable operation is forbidden, so mask the bit in attributes
+          // so as to keep consistent with the actual Status
+          //
+          // Attributes &= (~EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);
+          //
+          //
+          //
+          return EFI_UNSUPPORTED;
+
+        }
+      }
+
+      //
+      // It can be supported, so get ready to set the bit
+      //
+      Command |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
+    }
+  }
+
+  if ((Attributes & EFI_PCI_IO_ATTRIBUTE_IO) != 0) {
+    Command |= EFI_PCI_COMMAND_IO_SPACE;
+  }
+
+  if ((Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) != 0) {
+    Command |= EFI_PCI_COMMAND_MEMORY_SPACE;
+  }
+
+  if ((Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) != 0) {
+    Command |= EFI_PCI_COMMAND_BUS_MASTER;
+  }
+  //
+  // The upstream bridge should be also set to relevant attribute
+  // expect for IO, Mem and BusMaster
+  //
+  UpStreamAttributes = Attributes &
+                       (~(EFI_PCI_IO_ATTRIBUTE_IO     |
+                          EFI_PCI_IO_ATTRIBUTE_MEMORY |
+                          EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
+                          )
+                        );
+  UpStreamBridge = PciIoDevice->Parent;
+
+  if (Operation == EfiPciIoAttributeOperationEnable) {
+    //
+    // Enable relevant attributes to command register and bridge control register
+    //
+    Status = PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, Command);
+    if (BridgeControl != 0) {
+      Status = PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);
+    }
+
+    PciIoDevice->Attributes |= Attributes;
+
+    //
+    // Enable attributes of the upstream bridge
+    //
+    Status = UpStreamBridge->PciIo.Attributes (
+                                    &(UpStreamBridge->PciIo),
+                                    EfiPciIoAttributeOperationEnable,
+                                    UpStreamAttributes,
+                                    NULL
+                                    );
+  } else {
+
+    //
+    // Disable relevant attributes to command register and bridge control register
+    //
+    Status = PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, Command);
+    if (BridgeControl != 0) {
+      Status = PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);
+    }
+
+    PciIoDevice->Attributes &= (~Attributes);
+    Status = EFI_SUCCESS;
+
+  }
+
+  if (EFI_ERROR (Status)) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
+      PciIoDevice->DevicePath
+      );
+  }
+
+  return Status;
+}
+
+/**
+  Retrieve the AddrTranslationOffset from RootBridgeIo for the
+  specified range.
+
+  @param RootBridgeIo    Root Bridge IO instance.
+  @param AddrRangeMin    The base address of the MMIO.
+  @param AddrLen         The length of the MMIO.
+
+  @retval The AddrTranslationOffset from RootBridgeIo for the
+          specified range, or (UINT64) -1 if the range is not
+          found in RootBridgeIo.
+**/
+UINT64
+GetMmioAddressTranslationOffset (
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *RootBridgeIo,
+  UINT64                            AddrRangeMin,
+  UINT64                            AddrLen
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
+
+  Status = RootBridgeIo->Configuration (
+                           RootBridgeIo,
+                           (VOID **) &Configuration
+                           );
+  if (EFI_ERROR (Status)) {
+    return (UINT64) -1;
+  }
+
+  // According to UEFI 2.7, EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL::Configuration()
+  // returns host address instead of device address, while AddrTranslationOffset
+  // is not zero, and device address = host address + AddrTranslationOffset, so
+  // we convert host address to device address for range compare.
+  while (Configuration->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+    if ((Configuration->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) &&
+        (Configuration->AddrRangeMin + Configuration->AddrTranslationOffset <= AddrRangeMin) &&
+        (Configuration->AddrRangeMin + Configuration->AddrLen + Configuration->AddrTranslationOffset >= AddrRangeMin + AddrLen)
+        ) {
+      return Configuration->AddrTranslationOffset;
+    }
+    Configuration++;
+  }
+
+  //
+  // The resource occupied by BAR should be in the range reported by RootBridge.
+  //
+  ASSERT (FALSE);
+  return (UINT64) -1;
+}
+
+/**
+  Gets the attributes that this PCI controller supports setting on a BAR using
+  SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for resource range. The legal range for this field is 0..5.
+  @param  Supports              A pointer to the mask of attributes that this PCI controller supports
+                                setting for this BAR with SetBarAttributes().
+  @param  Resources             A pointer to the resource descriptors that describe the current
+                                configuration of this BAR of the PCI controller.
+
+  @retval EFI_SUCCESS           If Supports is not NULL, then the attributes that the PCI
+                                controller supports are returned in Supports. If Resources
+                                is not NULL, then the resource descriptors that the PCI
+                                controller is currently using are returned in Resources.
+  @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to allocate
+                                Resources.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoGetBarAttributes (
+  IN EFI_PCI_IO_PROTOCOL             * This,
+  IN  UINT8                          BarIndex,
+  OUT UINT64                         *Supports, OPTIONAL
+  OUT VOID                           **Resources OPTIONAL
+  )
+{
+  PCI_IO_DEVICE                     *PciIoDevice;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
+  EFI_ACPI_END_TAG_DESCRIPTOR       *End;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  if (Supports == NULL && Resources == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((BarIndex >= PCI_MAX_BAR) || (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // This driver does not support modifications to the WRITE_COMBINE or
+  // CACHED attributes for BAR ranges.
+  //
+  if (Supports != NULL) {
+    *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
+  }
+
+  if (Resources != NULL) {
+    Descriptor = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+    if (Descriptor == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    *Resources   = Descriptor;
+
+    Descriptor->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+    Descriptor->Len          = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
+    Descriptor->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;
+    Descriptor->AddrLen      = PciIoDevice->PciBar[BarIndex].Length;
+    Descriptor->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;
+
+    switch (PciIoDevice->PciBar[BarIndex].BarType) {
+    case PciBarTypeIo16:
+    case PciBarTypeIo32:
+      //
+      // Io
+      //
+      Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
+      break;
+
+    case PciBarTypePMem32:
+      //
+      // prefetchable
+      //
+      Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
+      //
+      // Fall through
+      //
+    case PciBarTypeMem32:
+      //
+      // Mem
+      //
+      Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+      //
+      // 32 bit
+      //
+      Descriptor->AddrSpaceGranularity = 32;
+      break;
+
+    case PciBarTypePMem64:
+      //
+      // prefetchable
+      //
+      Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
+      //
+      // Fall through
+      //
+    case PciBarTypeMem64:
+      //
+      // Mem
+      //
+      Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+      //
+      // 64 bit
+      //
+      Descriptor->AddrSpaceGranularity = 64;
+      break;
+
+    default:
+      break;
+    }
+
+    //
+    // put the checksum
+    //
+    End           = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);
+    End->Desc     = ACPI_END_TAG_DESCRIPTOR;
+    End->Checksum = 0;
+
+    //
+    // Get the Address Translation Offset
+    //
+    if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
+      Descriptor->AddrTranslationOffset = GetMmioAddressTranslationOffset (
+                                            PciIoDevice->PciRootBridgeIo,
+                                            Descriptor->AddrRangeMin,
+                                            Descriptor->AddrLen
+                                            );
+      if (Descriptor->AddrTranslationOffset == (UINT64) -1) {
+        FreePool (Descriptor);
+        return EFI_UNSUPPORTED;
+      }
+    }
+
+    // According to UEFI spec 2.7, we need return host address for
+    // PciIo->GetBarAttributes, and host address = device address - translation.
+    Descriptor->AddrRangeMin -= Descriptor->AddrTranslationOffset;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Sets the attributes for a range of a BAR on a PCI controller.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Attributes            The mask of attributes to set for the resource range specified by
+                                BarIndex, Offset, and Length.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for resource range. The legal range for this field is 0..5.
+  @param  Offset                A pointer to the BAR relative base address of the resource range to be
+                                modified by the attributes specified by Attributes.
+  @param  Length                A pointer to the length of the resource range to be modified by the
+                                attributes specified by Attributes.
+
+  @retval EFI_SUCCESS           The set of attributes specified by Attributes for the resource
+                                range specified by BarIndex, Offset, and Length were
+                                set on the PCI controller, and the actual resource range is returned
+                                in Offset and Length.
+  @retval EFI_INVALID_PARAMETER Offset or Length is NULL.
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources to set the attributes on the
+                                resource range specified by BarIndex, Offset, and
+                                Length.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoSetBarAttributes (
+  IN EFI_PCI_IO_PROTOCOL              *This,
+  IN     UINT64                       Attributes,
+  IN     UINT8                        BarIndex,
+  IN OUT UINT64                       *Offset,
+  IN OUT UINT64                       *Length
+  )
+{
+  EFI_STATUS    Status;
+  PCI_IO_DEVICE *PciIoDevice;
+  UINT64        NonRelativeOffset;
+  UINT64        Supports;
+
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+  //
+  // Make sure Offset and Length are not NULL
+  //
+  if (Offset == NULL || Length == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {
+    return EFI_UNSUPPORTED;
+  }
+  //
+  // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.
+  // If Attributes is not 0, then return EFI_UNSUPPORTED.
+  //
+  Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
+
+  if (Attributes != (Attributes & Supports)) {
+    return EFI_UNSUPPORTED;
+  }
+  //
+  // Attributes must be supported.  Make sure the BAR range described by BarIndex, Offset, and
+  // Length are valid for this PCI device.
+  //
+  NonRelativeOffset = *Offset;
+  Status = PciIoVerifyBarAccess (
+            PciIoDevice,
+            BarIndex,
+            PciBarTypeMem,
+            EfiPciIoWidthUint8,
+            (UINT32) *Length,
+            &NonRelativeOffset
+            );
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Test whether two Pci devices has same parent bridge.
+
+  @param PciDevice1  The first pci device for testing.
+  @param PciDevice2  The second pci device for testing.
+
+  @retval TRUE       Two Pci device has the same parent bridge.
+  @retval FALSE      Two Pci device has not the same parent bridge.
+
+**/
+BOOLEAN
+PciDevicesOnTheSamePath (
+  IN PCI_IO_DEVICE        *PciDevice1,
+  IN PCI_IO_DEVICE        *PciDevice2
+  )
+{
+  BOOLEAN   Existed1;
+  BOOLEAN   Existed2;
+
+  if (PciDevice1->Parent == PciDevice2->Parent) {
+    return TRUE;
+  }
+
+  Existed1 = PciDeviceExisted (PciDevice1->Parent, PciDevice2);
+  Existed2 = PciDeviceExisted (PciDevice2->Parent, PciDevice1);
+
+  return (BOOLEAN) (Existed1 || Existed2);
+}
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h
new file mode 100644
index 0000000000..c00516ee6a
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h
@@ -0,0 +1,660 @@
+/** @file
+  EFI PCI IO protocol functions declaration for PCI Bus module.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_PCI_IO_PROTOCOL_H_
+#define _EFI_PCI_IO_PROTOCOL_H_
+
+/**
+  Initializes a PCI I/O Instance.
+
+  @param PciIoDevice    Pci device instance.
+
+**/
+VOID
+InitializePciIoInstance (
+  IN PCI_IO_DEVICE               *PciIoDevice
+  );
+
+/**
+  Verifies access to a PCI Base Address Register (BAR).
+
+  @param PciIoDevice  Pci device instance.
+  @param BarIndex     The BAR index of the standard PCI Configuration header to use as the
+                      base address for the memory or I/O operation to perform.
+  @param Type         Operation type could be memory or I/O.
+  @param Width        Signifies the width of the memory or I/O operations.
+  @param Count        The number of memory or I/O operations to perform.
+  @param Offset       The offset within the PCI configuration space for the PCI controller.
+
+  @retval EFI_INVALID_PARAMETER Invalid Width/BarIndex or Bar type.
+  @retval EFI_SUCCESS           Successfully verified.
+
+**/
+EFI_STATUS
+PciIoVerifyBarAccess (
+  IN PCI_IO_DEVICE                   *PciIoDevice,
+  IN UINT8                           BarIndex,
+  IN PCI_BAR_TYPE                    Type,
+  IN IN EFI_PCI_IO_PROTOCOL_WIDTH    Width,
+  IN IN UINTN                        Count,
+  IN UINT64                          *Offset
+  );
+
+/**
+  Verifies access to a PCI Configuration Header.
+
+  @param PciIoDevice  Pci device instance.
+  @param Width        Signifies the width of the memory or I/O operations.
+  @param Count        The number of memory or I/O operations to perform.
+  @param Offset       The offset within the PCI configuration space for the PCI controller.
+
+  @retval EFI_INVALID_PARAMETER  Invalid Width
+  @retval EFI_UNSUPPORTED        Offset overflowed.
+  @retval EFI_SUCCESS            Successfully verified.
+
+**/
+EFI_STATUS
+PciIoVerifyConfigAccess (
+  IN PCI_IO_DEVICE              *PciIoDevice,
+  IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN UINTN                      Count,
+  IN UINT64                     *Offset
+  );
+
+/**
+  Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is
+  satisfied or after a defined duration.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory or I/O operations.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for the memory operation to perform.
+  @param  Offset                The offset within the selected BAR to start the memory operation.
+  @param  Mask                  Mask used for the polling criteria.
+  @param  Value                 The comparison value used for the polling exit criteria.
+  @param  Delay                 The number of 100 ns units to poll.
+  @param  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_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       Offset is not valid for the BarIndex of this PCI controller.
+  @retval EFI_TIMEOUT           Delay expired before a match occurred.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoPollMem (
+  IN  EFI_PCI_IO_PROTOCOL        *This,
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT8                      BarIndex,
+  IN  UINT64                     Offset,
+  IN  UINT64                     Mask,
+  IN  UINT64                     Value,
+  IN  UINT64                     Delay,
+  OUT UINT64                     *Result
+  );
+
+/**
+  Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is
+  satisfied or after a defined duration.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory or I/O operations.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for the memory operation to perform.
+  @param  Offset                The offset within the selected BAR to start the memory operation.
+  @param  Mask                  Mask used for the polling criteria.
+  @param  Value                 The comparison value used for the polling exit criteria.
+  @param  Delay                 The number of 100 ns units to poll.
+  @param  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_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       Offset is not valid for the BarIndex of this PCI controller.
+  @retval EFI_TIMEOUT           Delay expired before a match occurred.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoPollIo (
+  IN  EFI_PCI_IO_PROTOCOL        *This,
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT8                      BarIndex,
+  IN  UINT64                     Offset,
+  IN  UINT64                     Mask,
+  IN  UINT64                     Value,
+  IN  UINT64                     Delay,
+  OUT UINT64                     *Result
+  );
+
+/**
+  Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory or I/O operations.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for the memory or I/O operation to perform.
+  @param  Offset                The offset within the selected BAR to start the memory or I/O operation.
+  @param  Count                 The number of memory or I/O operations to perform.
+  @param  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 controller.
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI BAR specified by BarIndex.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoMemRead (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT8                      BarIndex,
+  IN     UINT64                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  );
+
+/**
+  Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory or I/O operations.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for the memory or I/O operation to perform.
+  @param  Offset                The offset within the selected BAR to start the memory or I/O operation.
+  @param  Count                 The number of memory or I/O operations to perform.
+  @param  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 controller.
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI BAR specified by BarIndex.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoMemWrite (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT8                      BarIndex,
+  IN     UINT64                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  );
+
+/**
+  Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory or I/O operations.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for the memory or I/O operation to perform.
+  @param  Offset                The offset within the selected BAR to start the memory or I/O operation.
+  @param  Count                 The number of memory or I/O operations to perform.
+  @param  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 controller.
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI BAR specified by BarIndex.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoIoRead (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT8                      BarIndex,
+  IN     UINT64                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  );
+
+/**
+  Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory or I/O operations.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for the memory or I/O operation to perform.
+  @param  Offset                The offset within the selected BAR to start the memory or I/O operation.
+  @param  Count                 The number of memory or I/O operations to perform.
+  @param  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 controller.
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI BAR specified by BarIndex.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoIoWrite (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT8                      BarIndex,
+  IN     UINT64                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  );
+
+/**
+  Enable a PCI driver to access PCI controller registers in PCI configuration space.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory operations.
+  @param  Offset                The offset within the PCI configuration space for the PCI controller.
+  @param  Count                 The number of PCI configuration operations to perform.
+  @param  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 controller.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI configuration header of the PCI controller.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoConfigRead (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT32                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  );
+
+/**
+  Enable a PCI driver to access PCI controller registers in PCI configuration space.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory operations.
+  @param  Offset                The offset within the PCI configuration space for the PCI controller.
+  @param  Count                 The number of PCI configuration operations to perform.
+  @param  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 controller.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI configuration header of the PCI controller.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoConfigWrite (
+  IN     EFI_PCI_IO_PROTOCOL        *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT32                     Offset,
+  IN     UINTN                      Count,
+  IN OUT VOID                       *Buffer
+  );
+
+/**
+  Enables a PCI driver to copy one region of PCI memory space to another region of PCI
+  memory space.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory operations.
+  @param  DestBarIndex          The BAR index in the standard PCI Configuration header to use as the
+                                base address for the memory operation to perform.
+  @param  DestOffset            The destination offset within the BAR specified by DestBarIndex to
+                                start the memory writes for the copy operation.
+  @param  SrcBarIndex           The BAR index in the standard PCI Configuration header to use as the
+                                base address for the memory operation to perform.
+  @param  SrcOffset             The source offset within the BAR specified by SrcBarIndex to start
+                                the memory reads for the copy operation.
+  @param  Count                 The number of memory operations to perform. Bytes moved is Width
+                                size * Count, starting at DestOffset and SrcOffset.
+
+  @retval EFI_SUCCESS           The data was copied from one memory region to another memory region.
+  @retval EFI_UNSUPPORTED       DestBarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       SrcBarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       The address range specified by DestOffset, Width, and Count
+                                is not valid for the PCI BAR specified by DestBarIndex.
+  @retval EFI_UNSUPPORTED       The address range specified by SrcOffset, Width, and Count is
+                                not valid for the PCI BAR specified by SrcBarIndex.
+  @retval EFI_INVALID_PARAMETER Width is invalid.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoCopyMem (
+  IN EFI_PCI_IO_PROTOCOL              *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,
+  IN     UINT8                        DestBarIndex,
+  IN     UINT64                       DestOffset,
+  IN     UINT8                        SrcBarIndex,
+  IN     UINT64                       SrcOffset,
+  IN     UINTN                        Count
+  );
+
+/**
+  Provides the PCI controller-specific addresses needed to access system memory.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Operation             Indicates if the bus master is going to read or write to system memory.
+  @param  HostAddress           The system memory address to map to the PCI controller.
+  @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes
+                                that were mapped.
+  @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to
+                                access the hosts HostAddress.
+  @param  Mapping               A resulting value to pass to Unmap().
+
+  @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.
+  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoMap (
+  IN     EFI_PCI_IO_PROTOCOL            *This,
+  IN     EFI_PCI_IO_PROTOCOL_OPERATION  Operation,
+  IN     VOID                           *HostAddress,
+  IN OUT UINTN                          *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,
+  OUT    VOID                           **Mapping
+  );
+
+/**
+  Completes the Map() operation and releases any corresponding resources.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Mapping               The mapping value returned from Map().
+
+  @retval EFI_SUCCESS           The range was unmapped.
+  @retval EFI_DEVICE_ERROR      The data was not committed to the target system memory.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoUnmap (
+  IN  EFI_PCI_IO_PROTOCOL  *This,
+  IN  VOID                 *Mapping
+  );
+
+/**
+  Allocates pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer
+  or EfiPciOperationBusMasterCommonBuffer64 mapping.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @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.
+
+  @retval EFI_SUCCESS           The requested memory pages were allocated.
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are
+                                MEMORY_WRITE_COMBINE, MEMORY_CACHED and DUAL_ADDRESS_CYCLE.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoAllocateBuffer (
+  IN  EFI_PCI_IO_PROTOCOL   *This,
+  IN  EFI_ALLOCATE_TYPE     Type,
+  IN  EFI_MEMORY_TYPE       MemoryType,
+  IN  UINTN                 Pages,
+  OUT VOID                  **HostAddress,
+  IN  UINT64                Attributes
+  );
+
+/**
+  Frees memory that was allocated with AllocateBuffer().
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @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
+PciIoFreeBuffer (
+  IN  EFI_PCI_IO_PROTOCOL   *This,
+  IN  UINTN                 Pages,
+  IN  VOID                  *HostAddress
+  );
+
+/**
+  Flushes all PCI posted write transactions from a PCI host bridge to system memory.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+
+  @retval EFI_SUCCESS           The PCI posted write transactions were flushed from the PCI host
+                                bridge to system memory.
+  @retval EFI_DEVICE_ERROR      The PCI posted write transactions were not flushed from the PCI
+                                host bridge due to a hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoFlush (
+  IN  EFI_PCI_IO_PROTOCOL  *This
+  );
+
+/**
+  Retrieves this PCI controller's current PCI bus number, device number, and function number.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  SegmentNumber         The PCI controller's current PCI segment number.
+  @param  BusNumber             The PCI controller's current PCI bus number.
+  @param  DeviceNumber          The PCI controller's current PCI device number.
+  @param  FunctionNumber        The PCI controller's current PCI function number.
+
+  @retval EFI_SUCCESS           The PCI controller location was returned.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoGetLocation (
+  IN  EFI_PCI_IO_PROTOCOL  *This,
+  OUT UINTN                *Segment,
+  OUT UINTN                *Bus,
+  OUT UINTN                *Device,
+  OUT UINTN                *Function
+  );
+
+/**
+  Check BAR type for PCI resource.
+
+  @param PciIoDevice   PCI device instance.
+  @param BarIndex      The BAR index of the standard PCI Configuration header to use as the
+                       base address for the memory or I/O operation to perform.
+  @param BarType       Memory or I/O.
+
+  @retval TRUE         Pci device's bar type is same with input BarType.
+  @retval TRUE         Pci device's bar type is not same with input BarType.
+
+**/
+BOOLEAN
+CheckBarType (
+  IN PCI_IO_DEVICE          *PciIoDevice,
+  IN UINT8                  BarIndex,
+  IN PCI_BAR_TYPE           BarType
+  );
+
+/**
+  Set/Disable new attributes to a Root Bridge.
+
+  @param  PciIoDevice  Pci device instance.
+  @param  Attributes   New attribute want to be set.
+  @param  Operation    Set or Disable.
+
+  @retval  EFI_UNSUPPORTED  If root bridge does not support change attribute.
+  @retval  EFI_SUCCESS      Successfully set new attributes.
+
+**/
+EFI_STATUS
+ModifyRootBridgeAttributes (
+  IN  PCI_IO_DEVICE                            *PciIoDevice,
+  IN  UINT64                                   Attributes,
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation
+  );
+
+/**
+  Check whether this device can be enable/disable to snoop.
+
+  @param PciIoDevice  Pci device instance.
+  @param Operation    Enable/Disable.
+
+  @retval EFI_UNSUPPORTED  Pci device is not GFX device or not support snoop.
+  @retval EFI_SUCCESS      Snoop can be supported.
+
+**/
+EFI_STATUS
+SupportPaletteSnoopAttributes (
+  IN PCI_IO_DEVICE                            *PciIoDevice,
+  IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation
+  );
+
+/**
+  Performs an operation on the attributes that this PCI controller supports. The operations include
+  getting the set of supported attributes, retrieving the current attributes, setting the current
+  attributes, enabling attributes, and disabling attributes.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Operation             The operation to perform on the attributes for this PCI controller.
+  @param  Attributes            The mask of attributes that are used for Set, Enable, and Disable
+                                operations.
+  @param  Result                A pointer to the result mask of attributes that are returned for the Get
+                                and Supported operations.
+
+  @retval EFI_SUCCESS           The operation on the PCI controller's attributes was completed.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_UNSUPPORTED       one or more of the bits set in
+                                Attributes are not supported by this PCI controller or one of
+                                its parent bridges when Operation is Set, Enable or Disable.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoAttributes (
+  IN EFI_PCI_IO_PROTOCOL                       * This,
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,
+  IN  UINT64                                   Attributes,
+  OUT UINT64                                   *Result OPTIONAL
+  );
+
+/**
+  Gets the attributes that this PCI controller supports setting on a BAR using
+  SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for resource range. The legal range for this field is 0..5.
+  @param  Supports              A pointer to the mask of attributes that this PCI controller supports
+                                setting for this BAR with SetBarAttributes().
+  @param  Resources             A pointer to the resource descriptors that describe the current
+                                configuration of this BAR of the PCI controller.
+
+  @retval EFI_SUCCESS           If Supports is not NULL, then the attributes that the PCI
+                                controller supports are returned in Supports. If Resources
+                                is not NULL, then the resource descriptors that the PCI
+                                controller is currently using are returned in Resources.
+  @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to allocate
+                                Resources.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoGetBarAttributes (
+  IN EFI_PCI_IO_PROTOCOL             * This,
+  IN  UINT8                          BarIndex,
+  OUT UINT64                         *Supports, OPTIONAL
+  OUT VOID                           **Resources OPTIONAL
+  );
+
+/**
+  Sets the attributes for a range of a BAR on a PCI controller.
+
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Attributes            The mask of attributes to set for the resource range specified by
+                                BarIndex, Offset, and Length.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for resource range. The legal range for this field is 0..5.
+  @param  Offset                A pointer to the BAR relative base address of the resource range to be
+                                modified by the attributes specified by Attributes.
+  @param  Length                A pointer to the length of the resource range to be modified by the
+                                attributes specified by Attributes.
+
+  @retval EFI_SUCCESS           The set of attributes specified by Attributes for the resource
+                                range specified by BarIndex, Offset, and Length were
+                                set on the PCI controller, and the actual resource range is returned
+                                in Offset and Length.
+  @retval EFI_INVALID_PARAMETER Offset or Length is NULL.
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources to set the attributes on the
+                                resource range specified by BarIndex, Offset, and
+                                Length.
+
+**/
+EFI_STATUS
+EFIAPI
+PciIoSetBarAttributes (
+  IN EFI_PCI_IO_PROTOCOL              *This,
+  IN     UINT64                       Attributes,
+  IN     UINT8                        BarIndex,
+  IN OUT UINT64                       *Offset,
+  IN OUT UINT64                       *Length
+  );
+
+
+/**
+  Test whether two Pci devices has same parent bridge.
+
+  @param PciDevice1  The first pci device for testing.
+  @param PciDevice2  The second pci device for testing.
+
+  @retval TRUE       Two Pci device has the same parent bridge.
+  @retval FALSE      Two Pci device has not the same parent bridge.
+
+**/
+BOOLEAN
+PciDevicesOnTheSamePath (
+  IN PCI_IO_DEVICE        *PciDevice1,
+  IN PCI_IO_DEVICE        *PciDevice2
+  );
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
new file mode 100644
index 0000000000..2b76100740
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
@@ -0,0 +1,1809 @@
+/** @file
+  Internal library implementation for PCI Bus module.
+
+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CHAR16 *mBarTypeStr[] = {
+  L"Unknow",
+  L"  Io16",
+  L"  Io32",
+  L" Mem32",
+  L"PMem32",
+  L" Mem64",
+  L"PMem64",
+  L" OpRom",
+  L"    Io",
+  L"   Mem",
+  L"Unknow"
+  };
+
+/**
+  Retrieve the max bus number that is assigned to the Root Bridge hierarchy.
+  It can support the case that there are multiple bus ranges.
+
+  @param  Bridge           Bridge device instance.
+
+  @retval                  The max bus number that is assigned to this Root Bridge hierarchy.
+
+**/
+UINT16
+PciGetMaxBusNumber (
+  IN PCI_IO_DEVICE                      *Bridge
+  )
+{
+  PCI_IO_DEVICE                      *RootBridge;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *BusNumberRanges;
+  UINT64                             MaxNumberInRange;
+
+  //
+  // Get PCI Root Bridge device
+  //
+  RootBridge = Bridge;
+  while (RootBridge->Parent != NULL) {
+    RootBridge = RootBridge->Parent;
+  }
+  MaxNumberInRange = 0;
+  //
+  // Iterate the bus number ranges to get max PCI bus number
+  //
+  BusNumberRanges = RootBridge->BusNumberRanges;
+  while (BusNumberRanges->Desc != ACPI_END_TAG_DESCRIPTOR) {
+    MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;
+    BusNumberRanges++;
+  }
+  return (UINT16) MaxNumberInRange;
+}
+
+/**
+  Retrieve the PCI Card device BAR information via PciIo interface.
+
+  @param PciIoDevice        PCI Card device instance.
+
+**/
+VOID
+GetBackPcCardBar (
+  IN  PCI_IO_DEVICE                  *PciIoDevice
+  )
+{
+  UINT32  Address;
+
+  if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+    return;
+  }
+
+  //
+  // Read PciBar information from the bar register
+  //
+  if (!gFullEnumeration) {
+    Address = 0;
+    PciIoDevice->PciIo.Pci.Read (
+                             &(PciIoDevice->PciIo),
+                             EfiPciIoWidthUint32,
+                             PCI_CARD_MEMORY_BASE_0,
+                             1,
+                             &Address
+                             );
+
+    (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress  = (UINT64) (Address);
+    (PciIoDevice->PciBar)[P2C_MEM_1].Length       = 0x2000000;
+    (PciIoDevice->PciBar)[P2C_MEM_1].BarType      = PciBarTypeMem32;
+
+    Address = 0;
+    PciIoDevice->PciIo.Pci.Read (
+                             &(PciIoDevice->PciIo),
+                             EfiPciIoWidthUint32,
+                             PCI_CARD_MEMORY_BASE_1,
+                             1,
+                             &Address
+                             );
+    (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress  = (UINT64) (Address);
+    (PciIoDevice->PciBar)[P2C_MEM_2].Length       = 0x2000000;
+    (PciIoDevice->PciBar)[P2C_MEM_2].BarType      = PciBarTypePMem32;
+
+    Address = 0;
+    PciIoDevice->PciIo.Pci.Read (
+                             &(PciIoDevice->PciIo),
+                             EfiPciIoWidthUint32,
+                             PCI_CARD_IO_BASE_0_LOWER,
+                             1,
+                             &Address
+                             );
+    (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address);
+    (PciIoDevice->PciBar)[P2C_IO_1].Length      = 0x100;
+    (PciIoDevice->PciBar)[P2C_IO_1].BarType     = PciBarTypeIo16;
+
+    Address = 0;
+    PciIoDevice->PciIo.Pci.Read (
+                             &(PciIoDevice->PciIo),
+                             EfiPciIoWidthUint32,
+                             PCI_CARD_IO_BASE_1_LOWER,
+                             1,
+                             &Address
+                             );
+    (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address);
+    (PciIoDevice->PciBar)[P2C_IO_2].Length      = 0x100;
+    (PciIoDevice->PciBar)[P2C_IO_2].BarType     = PciBarTypeIo16;
+
+  }
+
+  if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+    GetResourcePaddingForHpb (PciIoDevice);
+  }
+}
+
+/**
+  Remove rejected pci device from specific root bridge
+  handle.
+
+  @param RootBridgeHandle  Specific parent root bridge handle.
+  @param Bridge            Bridge device instance.
+
+**/
+VOID
+RemoveRejectedPciDevices (
+  IN EFI_HANDLE        RootBridgeHandle,
+  IN PCI_IO_DEVICE     *Bridge
+  )
+{
+  PCI_IO_DEVICE   *Temp;
+  LIST_ENTRY      *CurrentLink;
+  LIST_ENTRY      *LastLink;
+
+  if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+    return;
+  }
+
+  CurrentLink = Bridge->ChildList.ForwardLink;
+
+  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
+
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    if (IS_PCI_BRIDGE (&Temp->Pci)) {
+      //
+      // Remove rejected devices recusively
+      //
+      RemoveRejectedPciDevices (RootBridgeHandle, Temp);
+    } else {
+      //
+      // Skip rejection for all PPBs, while detect rejection for others
+      //
+      if (IsPciDeviceRejected (Temp)) {
+
+        //
+        // For P2C, remove all devices on it
+        //
+        if (!IsListEmpty (&Temp->ChildList)) {
+          RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);
+        }
+
+        //
+        // Finally remove itself
+        //
+        LastLink = CurrentLink->BackLink;
+        RemoveEntryList (CurrentLink);
+        FreePciDevice (Temp);
+
+        CurrentLink = LastLink;
+      }
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+}
+
+/**
+  Dump the resourc map of the bridge device.
+
+  @param[in] BridgeResource   Resource descriptor of the bridge device.
+**/
+VOID
+DumpBridgeResource (
+  IN PCI_RESOURCE_NODE     *BridgeResource
+  )
+{
+  LIST_ENTRY               *Link;
+  PCI_RESOURCE_NODE        *Resource;
+  PCI_BAR                  *Bar;
+
+  if ((BridgeResource != NULL) && (BridgeResource->Length != 0)) {
+    DEBUG ((
+      EFI_D_INFO, "Type = %s; Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx\n",
+      mBarTypeStr[MIN (BridgeResource->ResType, PciBarTypeMaxType)],
+      BridgeResource->PciDev->PciBar[BridgeResource->Bar].BaseAddress,
+      BridgeResource->Length, BridgeResource->Alignment
+      ));
+    for ( Link = GetFirstNode (&BridgeResource->ChildList)
+        ; !IsNull (&BridgeResource->ChildList, Link)
+        ; Link = GetNextNode (&BridgeResource->ChildList, Link)
+        ) {
+      Resource = RESOURCE_NODE_FROM_LINK (Link);
+      if (Resource->ResourceUsage == PciResUsageTypical) {
+        Bar = Resource->Virtual ? Resource->PciDev->VfPciBar : Resource->PciDev->PciBar;
+        DEBUG ((
+          EFI_D_INFO, "   Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx;\tOwner = %s [%02x|%02x|%02x:",
+          Bar[Resource->Bar].BaseAddress, Resource->Length, Resource->Alignment,
+          IS_PCI_BRIDGE (&Resource->PciDev->Pci)     ? L"PPB" :
+          IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) ? L"P2C" :
+                                                       L"PCI",
+          Resource->PciDev->BusNumber, Resource->PciDev->DeviceNumber,
+          Resource->PciDev->FunctionNumber
+          ));
+
+        if ((!IS_PCI_BRIDGE (&Resource->PciDev->Pci) && !IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci)) ||
+            (IS_PCI_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < PPB_IO_RANGE)) ||
+            (IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < P2C_MEM_1))
+            ) {
+          //
+          // The resource requirement comes from the device itself.
+          //
+          DEBUG ((EFI_D_INFO, "%02x]", Bar[Resource->Bar].Offset));
+        } else {
+          //
+          // The resource requirement comes from the subordinate devices.
+          //
+          DEBUG ((EFI_D_INFO, "**]"));
+        }
+      } else {
+        DEBUG ((EFI_D_INFO, "   Base = Padding;\tLength = 0x%lx;\tAlignment = 0x%lx", Resource->Length, Resource->Alignment));
+      }
+      if (BridgeResource->ResType != Resource->ResType) {
+        DEBUG ((EFI_D_INFO, "; Type = %s", mBarTypeStr[MIN (Resource->ResType, PciBarTypeMaxType)]));
+      }
+      DEBUG ((EFI_D_INFO, "\n"));
+    }
+  }
+}
+
+/**
+  Find the corresponding resource node for the Device in child list of BridgeResource.
+
+  @param[in]  Device          Pointer to PCI_IO_DEVICE.
+  @param[in]  BridgeResource  Pointer to PCI_RESOURCE_NODE.
+  @param[out] DeviceResources Pointer to a buffer to receive resources for the Device.
+
+  @return Count of the resource descriptors returned.
+**/
+UINTN
+FindResourceNode (
+  IN  PCI_IO_DEVICE     *Device,
+  IN  PCI_RESOURCE_NODE *BridgeResource,
+  OUT PCI_RESOURCE_NODE **DeviceResources OPTIONAL
+  )
+{
+  LIST_ENTRY               *Link;
+  PCI_RESOURCE_NODE        *Resource;
+  UINTN                    Count;
+
+  Count = 0;
+  for ( Link = BridgeResource->ChildList.ForwardLink
+      ; Link != &BridgeResource->ChildList
+      ; Link = Link->ForwardLink
+      ) {
+    Resource = RESOURCE_NODE_FROM_LINK (Link);
+    if (Resource->PciDev == Device) {
+      if (DeviceResources != NULL) {
+        DeviceResources[Count] = Resource;
+      }
+      Count++;
+    }
+  }
+
+  return Count;
+}
+
+/**
+  Dump the resource map of all the devices under Bridge.
+
+  @param[in] Bridge        Bridge device instance.
+  @param[in] Resources     Resource descriptors for the bridge device.
+  @param[in] ResourceCount Count of resource descriptors.
+**/
+VOID
+DumpResourceMap (
+  IN PCI_IO_DEVICE     *Bridge,
+  IN PCI_RESOURCE_NODE **Resources,
+  IN UINTN             ResourceCount
+  )
+{
+  EFI_STATUS           Status;
+  LIST_ENTRY           *Link;
+  PCI_IO_DEVICE        *Device;
+  UINTN                Index;
+  CHAR16               *Str;
+  PCI_RESOURCE_NODE    **ChildResources;
+  UINTN                ChildResourceCount;
+
+  DEBUG ((EFI_D_INFO, "PciBus: Resource Map for "));
+
+  Status = gBS->OpenProtocol (
+                  Bridge->Handle,
+                  &gEfiPciRootBridgeIoProtocolGuid,
+                  NULL,
+                  NULL,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      EFI_D_INFO, "Bridge [%02x|%02x|%02x]\n",
+      Bridge->BusNumber, Bridge->DeviceNumber, Bridge->FunctionNumber
+      ));
+  } else {
+    Str = ConvertDevicePathToText (
+            DevicePathFromHandle (Bridge->Handle),
+            FALSE,
+            FALSE
+            );
+    DEBUG ((EFI_D_INFO, "Root Bridge %s\n", Str != NULL ? Str : L""));
+    if (Str != NULL) {
+      FreePool (Str);
+    }
+  }
+
+  for (Index = 0; Index < ResourceCount; Index++) {
+    DumpBridgeResource (Resources[Index]);
+  }
+  DEBUG ((EFI_D_INFO, "\n"));
+
+  for ( Link = Bridge->ChildList.ForwardLink
+      ; Link != &Bridge->ChildList
+      ; Link = Link->ForwardLink
+      ) {
+    Device = PCI_IO_DEVICE_FROM_LINK (Link);
+    if (IS_PCI_BRIDGE (&Device->Pci)) {
+
+      ChildResourceCount = 0;
+      for (Index = 0; Index < ResourceCount; Index++) {
+        ChildResourceCount += FindResourceNode (Device, Resources[Index], NULL);
+      }
+      ChildResources = AllocatePool (sizeof (PCI_RESOURCE_NODE *) * ChildResourceCount);
+      ASSERT (ChildResources != NULL);
+      ChildResourceCount = 0;
+      for (Index = 0; Index < ResourceCount; Index++) {
+        ChildResourceCount += FindResourceNode (Device, Resources[Index], &ChildResources[ChildResourceCount]);
+      }
+
+      DumpResourceMap (Device, ChildResources, ChildResourceCount);
+      FreePool (ChildResources);
+    }
+  }
+}
+
+/**
+  Adjust the Devices' BAR size to minimum value if it support Resizeable BAR capability.
+
+  @param RootBridgeDev  Pointer to instance of PCI_IO_DEVICE..
+
+  @return TRUE if BAR size is adjusted.
+
+**/
+BOOLEAN
+AdjustPciDeviceBarSize (
+  IN PCI_IO_DEVICE *RootBridgeDev
+  )
+{
+  PCI_IO_DEVICE     *PciIoDevice;
+  LIST_ENTRY        *CurrentLink;
+  BOOLEAN           Adjusted;
+  UINTN             Offset;
+  UINTN             BarIndex;
+
+  Adjusted    = FALSE;
+  CurrentLink = RootBridgeDev->ChildList.ForwardLink;
+
+  while (CurrentLink != NULL && CurrentLink != &RootBridgeDev->ChildList) {
+    PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
+      if (AdjustPciDeviceBarSize (PciIoDevice)) {
+        Adjusted = TRUE;
+      }
+    } else {
+      if (PciIoDevice->ResizableBarOffset != 0) {
+        DEBUG ((
+          DEBUG_ERROR,
+          "PciBus: [%02x|%02x|%02x] Adjust Pci Device Bar Size\n",
+          PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber
+          ));
+        PciProgramResizableBar (PciIoDevice, PciResizableBarMin);
+        //
+        // Start to parse the bars
+        //
+        for (Offset = 0x10, BarIndex = 0; Offset <= 0x24 && BarIndex < PCI_MAX_BAR; BarIndex++) {
+          Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
+        }
+        Adjusted = TRUE;
+        DEBUG_CODE (DumpPciBars (PciIoDevice););
+      }
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return Adjusted;
+}
+
+/**
+  Submits the I/O and memory resource requirements for the specified PCI Host Bridge.
+
+  @param PciResAlloc  Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
+
+  @retval EFI_SUCCESS           Successfully finished resource allocation.
+  @retval EFI_NOT_FOUND         Cannot get root bridge instance.
+  @retval EFI_OUT_OF_RESOURCES  Platform failed to program the resources if no hot plug supported.
+  @retval other                 Some error occurred when allocating resources for the PCI Host Bridge.
+
+  @note   Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
+
+**/
+EFI_STATUS
+PciHostBridgeResourceAllocator (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+  )
+{
+  PCI_IO_DEVICE                                  *RootBridgeDev;
+  EFI_HANDLE                                     RootBridgeHandle;
+  VOID                                           *AcpiConfig;
+  EFI_STATUS                                     Status;
+  UINT64                                         IoBase;
+  UINT64                                         Mem32Base;
+  UINT64                                         PMem32Base;
+  UINT64                                         Mem64Base;
+  UINT64                                         PMem64Base;
+  UINT64                                         IoResStatus;
+  UINT64                                         Mem32ResStatus;
+  UINT64                                         PMem32ResStatus;
+  UINT64                                         Mem64ResStatus;
+  UINT64                                         PMem64ResStatus;
+  UINT32                                         MaxOptionRomSize;
+  PCI_RESOURCE_NODE                              *IoBridge;
+  PCI_RESOURCE_NODE                              *Mem32Bridge;
+  PCI_RESOURCE_NODE                              *PMem32Bridge;
+  PCI_RESOURCE_NODE                              *Mem64Bridge;
+  PCI_RESOURCE_NODE                              *PMem64Bridge;
+  PCI_RESOURCE_NODE                              IoPool;
+  PCI_RESOURCE_NODE                              Mem32Pool;
+  PCI_RESOURCE_NODE                              PMem32Pool;
+  PCI_RESOURCE_NODE                              Mem64Pool;
+  PCI_RESOURCE_NODE                              PMem64Pool;
+  EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD        HandleExtendedData;
+  EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD  AllocFailExtendedData;
+  BOOLEAN                                        ResizableBarNeedAdjust;
+  BOOLEAN                                        ResizableBarAdjusted;
+
+  ResizableBarNeedAdjust = PcdGetBool (PcdPcieResizableBarSupport);
+
+  //
+  // It may try several times if the resource allocation fails
+  //
+  while (TRUE) {
+    //
+    // Initialize resource pool
+    //
+    InitializeResourcePool (&IoPool, PciBarTypeIo16);
+    InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);
+    InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);
+    InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);
+    InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);
+
+    RootBridgeDev     = NULL;
+    RootBridgeHandle  = 0;
+
+    while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+      //
+      // Get Root Bridge Device by handle
+      //
+      RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+
+      if (RootBridgeDev == NULL) {
+        return EFI_NOT_FOUND;
+      }
+
+      //
+      // Create the entire system resource map from the information collected by
+      // enumerator. Several resource tree was created
+      //
+
+      //
+      // If non-standard PCI Bridge I/O window alignment is supported,
+      // set I/O aligment to minimum possible alignment for root bridge.
+      //
+      IoBridge = CreateResourceNode (
+                   RootBridgeDev,
+                   0,
+                   FeaturePcdGet (PcdPciBridgeIoAlignmentProbe) ? 0x1FF: 0xFFF,
+                   RB_IO_RANGE,
+                   PciBarTypeIo16,
+                   PciResUsageTypical
+                   );
+
+      Mem32Bridge = CreateResourceNode (
+                      RootBridgeDev,
+                      0,
+                      0xFFFFF,
+                      RB_MEM32_RANGE,
+                      PciBarTypeMem32,
+                      PciResUsageTypical
+                      );
+
+      PMem32Bridge = CreateResourceNode (
+                       RootBridgeDev,
+                       0,
+                       0xFFFFF,
+                       RB_PMEM32_RANGE,
+                       PciBarTypePMem32,
+                       PciResUsageTypical
+                       );
+
+      Mem64Bridge = CreateResourceNode (
+                      RootBridgeDev,
+                      0,
+                      0xFFFFF,
+                      RB_MEM64_RANGE,
+                      PciBarTypeMem64,
+                      PciResUsageTypical
+                      );
+
+      PMem64Bridge = CreateResourceNode (
+                       RootBridgeDev,
+                       0,
+                       0xFFFFF,
+                       RB_PMEM64_RANGE,
+                       PciBarTypePMem64,
+                       PciResUsageTypical
+                       );
+
+      //
+      // Get the max ROM size that the root bridge can process
+      // Insert to resource map so that there will be dedicate MEM32 resource range for Option ROM.
+      // All devices' Option ROM share the same MEM32 resource.
+      //
+      MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
+      if (MaxOptionRomSize != 0) {
+        RootBridgeDev->PciBar[0].BarType   = PciBarTypeOpRom;
+        RootBridgeDev->PciBar[0].Length    = MaxOptionRomSize;
+        RootBridgeDev->PciBar[0].Alignment = MaxOptionRomSize - 1;
+        GetResourceFromDevice (RootBridgeDev, IoBridge, Mem32Bridge, PMem32Bridge, Mem64Bridge, PMem64Bridge);
+      }
+
+      //
+      // Create resourcemap by going through all the devices subject to this root bridge
+      //
+      CreateResourceMap (
+        RootBridgeDev,
+        IoBridge,
+        Mem32Bridge,
+        PMem32Bridge,
+        Mem64Bridge,
+        PMem64Bridge
+        );
+
+      //
+      // Based on the all the resource tree, construct ACPI resource node to
+      // submit the resource aperture to pci host bridge protocol
+      //
+      Status = ConstructAcpiResourceRequestor (
+                 RootBridgeDev,
+                 IoBridge,
+                 Mem32Bridge,
+                 PMem32Bridge,
+                 Mem64Bridge,
+                 PMem64Bridge,
+                 &AcpiConfig
+                 );
+
+      //
+      // Insert these resource nodes into the database
+      //
+      InsertResourceNode (&IoPool, IoBridge);
+      InsertResourceNode (&Mem32Pool, Mem32Bridge);
+      InsertResourceNode (&PMem32Pool, PMem32Bridge);
+      InsertResourceNode (&Mem64Pool, Mem64Bridge);
+      InsertResourceNode (&PMem64Pool, PMem64Bridge);
+
+      if (Status == EFI_SUCCESS) {
+        //
+        // Submit the resource requirement
+        //
+        Status = PciResAlloc->SubmitResources (
+                                PciResAlloc,
+                                RootBridgeDev->Handle,
+                                AcpiConfig
+                                );
+        //
+        // If SubmitResources returns error, PciBus isn't able to start.
+        // It's a fatal error so assertion is added.
+        //
+        DEBUG ((EFI_D_INFO, "PciBus: HostBridge->SubmitResources() - %r\n", Status));
+        ASSERT_EFI_ERROR (Status);
+      }
+
+      //
+      // Free acpi resource node
+      //
+      if (AcpiConfig != NULL) {
+        FreePool (AcpiConfig);
+      }
+
+      if (EFI_ERROR (Status)) {
+        //
+        // Destroy all the resource tree
+        //
+        DestroyResourceTree (&IoPool);
+        DestroyResourceTree (&Mem32Pool);
+        DestroyResourceTree (&PMem32Pool);
+        DestroyResourceTree (&Mem64Pool);
+        DestroyResourceTree (&PMem64Pool);
+        return Status;
+      }
+    }
+    //
+    // End while, at least one Root Bridge should be found.
+    //
+    ASSERT (RootBridgeDev != NULL);
+
+    //
+    // Notify platform to start to program the resource
+    //
+    Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);
+    DEBUG ((EFI_D_INFO, "PciBus: HostBridge->NotifyPhase(AllocateResources) - %r\n", Status));
+    if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+      //
+      // If Hot Plug is not supported
+      //
+      if (EFI_ERROR (Status)) {
+        //
+        // Allocation failed, then return
+        //
+        return EFI_OUT_OF_RESOURCES;
+      }
+      //
+      // Allocation succeed.
+      // Get host bridge handle for status report, and then skip the main while
+      //
+      HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
+
+      break;
+
+    } else {
+      //
+      // If Hot Plug is supported
+      //
+      if (!EFI_ERROR (Status)) {
+        //
+        // Allocation succeed, then continue the following
+        //
+        break;
+      }
+
+      //
+      // If the resource allocation is unsuccessful, free resources on bridge
+      //
+
+      RootBridgeDev     = NULL;
+      RootBridgeHandle  = 0;
+
+      IoResStatus       = EFI_RESOURCE_SATISFIED;
+      Mem32ResStatus    = EFI_RESOURCE_SATISFIED;
+      PMem32ResStatus   = EFI_RESOURCE_SATISFIED;
+      Mem64ResStatus    = EFI_RESOURCE_SATISFIED;
+      PMem64ResStatus   = EFI_RESOURCE_SATISFIED;
+
+      while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+        //
+        // Get RootBridg Device by handle
+        //
+        RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+        if (RootBridgeDev == NULL) {
+          return EFI_NOT_FOUND;
+        }
+
+        //
+        // Get host bridge handle for status report
+        //
+        HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
+
+        //
+        // Get acpi resource node for all the resource types
+        //
+        AcpiConfig = NULL;
+
+        Status = PciResAlloc->GetProposedResources (
+                                PciResAlloc,
+                                RootBridgeDev->Handle,
+                                &AcpiConfig
+                                );
+
+        if (EFI_ERROR (Status)) {
+          return Status;
+        }
+
+        if (AcpiConfig != NULL) {
+          //
+          // Adjust resource allocation policy for each RB
+          //
+          GetResourceAllocationStatus (
+            AcpiConfig,
+            &IoResStatus,
+            &Mem32ResStatus,
+            &PMem32ResStatus,
+            &Mem64ResStatus,
+            &PMem64ResStatus
+            );
+          FreePool (AcpiConfig);
+        }
+      }
+      //
+      // End while
+      //
+
+      //
+      // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
+      //
+      //
+      // It is very difficult to follow the spec here
+      // Device path , Bar index can not be get here
+      //
+      ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
+
+      REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
+            EFI_PROGRESS_CODE,
+            EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
+            (VOID *) &AllocFailExtendedData,
+            sizeof (AllocFailExtendedData)
+            );
+
+     //
+     // When resource conflict happens, adjust the BAR size first.
+     // Only when adjusting BAR size doesn't help or BAR size cannot be adjusted,
+     // reject the device who requests largest resource that causes conflict.
+     //
+      ResizableBarAdjusted = FALSE;
+      if (ResizableBarNeedAdjust) {
+        ResizableBarAdjusted = AdjustPciDeviceBarSize (RootBridgeDev);
+        ResizableBarNeedAdjust = FALSE;
+      }
+      if (!ResizableBarAdjusted) {
+        Status = PciHostBridgeAdjustAllocation (
+                  &IoPool,
+                  &Mem32Pool,
+                  &PMem32Pool,
+                  &Mem64Pool,
+                  &PMem64Pool,
+                  IoResStatus,
+                  Mem32ResStatus,
+                  PMem32ResStatus,
+                  Mem64ResStatus,
+                  PMem64ResStatus
+                  );
+      }
+      //
+      // Destroy all the resource tree
+      //
+      DestroyResourceTree (&IoPool);
+      DestroyResourceTree (&Mem32Pool);
+      DestroyResourceTree (&PMem32Pool);
+      DestroyResourceTree (&Mem64Pool);
+      DestroyResourceTree (&PMem64Pool);
+
+      NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);
+
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+    }
+  }
+  //
+  // End main while
+  //
+
+  //
+  // Raise the EFI_IOB_PCI_RES_ALLOC status code
+  //
+  REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
+        EFI_PROGRESS_CODE,
+        EFI_IO_BUS_PCI | EFI_IOB_PCI_RES_ALLOC,
+        (VOID *) &HandleExtendedData,
+        sizeof (HandleExtendedData)
+        );
+
+  //
+  // Notify pci bus driver starts to program the resource
+  //
+  Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  RootBridgeDev     = NULL;
+
+  RootBridgeHandle  = 0;
+
+  while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+    //
+    // Get RootBridg Device by handle
+    //
+    RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+
+    if (RootBridgeDev == NULL) {
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // Get acpi resource node for all the resource types
+    //
+    AcpiConfig = NULL;
+    Status = PciResAlloc->GetProposedResources (
+                            PciResAlloc,
+                            RootBridgeDev->Handle,
+                            &AcpiConfig
+                            );
+
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    //
+    // Get the resource base by interpreting acpi resource node
+    //
+    //
+    GetResourceBase (
+      AcpiConfig,
+      &IoBase,
+      &Mem32Base,
+      &PMem32Base,
+      &Mem64Base,
+      &PMem64Base
+      );
+
+    //
+    // Create the entire system resource map from the information collected by
+    // enumerator. Several resource tree was created
+    //
+    FindResourceNode (RootBridgeDev, &IoPool, &IoBridge);
+    FindResourceNode (RootBridgeDev, &Mem32Pool, &Mem32Bridge);
+    FindResourceNode (RootBridgeDev, &PMem32Pool, &PMem32Bridge);
+    FindResourceNode (RootBridgeDev, &Mem64Pool, &Mem64Bridge);
+    FindResourceNode (RootBridgeDev, &PMem64Pool, &PMem64Bridge);
+
+    ASSERT (IoBridge     != NULL);
+    ASSERT (Mem32Bridge  != NULL);
+    ASSERT (PMem32Bridge != NULL);
+    ASSERT (Mem64Bridge  != NULL);
+    ASSERT (PMem64Bridge != NULL);
+
+    //
+    // Program IO resources
+    //
+    ProgramResource (
+      IoBase,
+      IoBridge
+      );
+
+    //
+    // Program Mem32 resources
+    //
+    ProgramResource (
+      Mem32Base,
+      Mem32Bridge
+      );
+
+    //
+    // Program PMem32 resources
+    //
+    ProgramResource (
+      PMem32Base,
+      PMem32Bridge
+      );
+
+    //
+    // Program Mem64 resources
+    //
+    ProgramResource (
+      Mem64Base,
+      Mem64Bridge
+      );
+
+    //
+    // Program PMem64 resources
+    //
+    ProgramResource (
+      PMem64Base,
+      PMem64Bridge
+      );
+
+    //
+    // Process Option ROM for this root bridge after all BARs are programmed.
+    // The PPB's MEM32 RANGE BAR is re-programmed to the Option ROM BAR Base in order to
+    // shadow the Option ROM of the devices under the PPB.
+    // After the shadow, Option ROM BAR decoding is turned off and the PPB's MEM32 RANGE
+    // BAR is restored back to the original value.
+    // The original value is programmed by ProgramResource() above.
+    //
+    DEBUG ((
+      DEBUG_INFO, "Process Option ROM: BAR Base/Length = %lx/%lx\n",
+      RootBridgeDev->PciBar[0].BaseAddress, RootBridgeDev->PciBar[0].Length
+      ));
+    ProcessOptionRom (RootBridgeDev, RootBridgeDev->PciBar[0].BaseAddress, RootBridgeDev->PciBar[0].Length);
+
+    IoBridge    ->PciDev->PciBar[IoBridge    ->Bar].BaseAddress = IoBase;
+    Mem32Bridge ->PciDev->PciBar[Mem32Bridge ->Bar].BaseAddress = Mem32Base;
+    PMem32Bridge->PciDev->PciBar[PMem32Bridge->Bar].BaseAddress = PMem32Base;
+    Mem64Bridge ->PciDev->PciBar[Mem64Bridge ->Bar].BaseAddress = Mem64Base;
+    PMem64Bridge->PciDev->PciBar[PMem64Bridge->Bar].BaseAddress = PMem64Base;
+
+    //
+    // Dump the resource map for current root bridge
+    //
+    DEBUG_CODE (
+      PCI_RESOURCE_NODE *Resources[5];
+      Resources[0] = IoBridge;
+      Resources[1] = Mem32Bridge;
+      Resources[2] = PMem32Bridge;
+      Resources[3] = Mem64Bridge;
+      Resources[4] = PMem64Bridge;
+      DumpResourceMap (RootBridgeDev, Resources, ARRAY_SIZE (Resources));
+    );
+
+    FreePool (AcpiConfig);
+  }
+
+  //
+  // Destroy all the resource tree
+  //
+  DestroyResourceTree (&IoPool);
+  DestroyResourceTree (&Mem32Pool);
+  DestroyResourceTree (&PMem32Pool);
+  DestroyResourceTree (&Mem64Pool);
+  DestroyResourceTree (&PMem64Pool);
+
+  //
+  // Notify the resource allocation phase is to end
+  //
+  Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
+
+  return Status;
+}
+
+/**
+  Allocate NumberOfBuses buses and return the next available PCI bus number.
+
+  @param  Bridge           Bridge device instance.
+  @param  StartBusNumber   Current available PCI bus number.
+  @param  NumberOfBuses    Number of buses enumerated below the StartBusNumber.
+  @param  NextBusNumber    Next available PCI bus number.
+
+  @retval EFI_SUCCESS           Available bus number resource is enough. Next available PCI bus number
+                                is returned in NextBusNumber.
+  @retval EFI_OUT_OF_RESOURCES  Available bus number resource is not enough for allocation.
+
+**/
+EFI_STATUS
+PciAllocateBusNumber (
+  IN PCI_IO_DEVICE                      *Bridge,
+  IN UINT8                              StartBusNumber,
+  IN UINT8                              NumberOfBuses,
+  OUT UINT8                             *NextBusNumber
+  )
+{
+  PCI_IO_DEVICE                      *RootBridge;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *BusNumberRanges;
+  UINT8                              NextNumber;
+  UINT64                             MaxNumberInRange;
+
+  //
+  // Get PCI Root Bridge device
+  //
+  RootBridge = Bridge;
+  while (RootBridge->Parent != NULL) {
+    RootBridge = RootBridge->Parent;
+  }
+
+  //
+  // Get next available PCI bus number
+  //
+  BusNumberRanges = RootBridge->BusNumberRanges;
+  while (BusNumberRanges->Desc != ACPI_END_TAG_DESCRIPTOR) {
+    MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;
+    if (StartBusNumber >= BusNumberRanges->AddrRangeMin && StartBusNumber <=  MaxNumberInRange) {
+      NextNumber = (UINT8)(StartBusNumber + NumberOfBuses);
+      while (NextNumber > MaxNumberInRange) {
+        ++BusNumberRanges;
+        if (BusNumberRanges->Desc == ACPI_END_TAG_DESCRIPTOR) {
+          return EFI_OUT_OF_RESOURCES;
+        }
+        NextNumber = (UINT8)(NextNumber + (BusNumberRanges->AddrRangeMin - (MaxNumberInRange + 1)));
+        MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;
+      }
+      *NextBusNumber = NextNumber;
+      return EFI_SUCCESS;
+    }
+    BusNumberRanges++;
+  }
+  return EFI_OUT_OF_RESOURCES;
+}
+
+/**
+  Scan pci bus and assign bus number to the given PCI bus system.
+
+  @param  Bridge           Bridge device instance.
+  @param  StartBusNumber   start point.
+  @param  SubBusNumber     Point to sub bus number.
+  @param  PaddedBusRange   Customized bus number.
+
+  @retval EFI_SUCCESS      Successfully scanned and assigned bus number.
+  @retval other            Some error occurred when scanning pci bus.
+
+  @note   Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
+
+**/
+EFI_STATUS
+PciScanBus (
+  IN PCI_IO_DEVICE                      *Bridge,
+  IN UINT8                              StartBusNumber,
+  OUT UINT8                             *SubBusNumber,
+  OUT UINT8                             *PaddedBusRange
+  )
+{
+  EFI_STATUS                        Status;
+  PCI_TYPE00                        Pci;
+  UINT8                             Device;
+  UINT8                             Func;
+  UINT64                            Address;
+  UINT8                             SecondBus;
+  UINT8                             PaddedSubBus;
+  UINT16                            Register;
+  UINTN                             HpIndex;
+  PCI_IO_DEVICE                     *PciDevice;
+  EFI_EVENT                         Event;
+  EFI_HPC_STATE                     State;
+  UINT64                            PciAddress;
+  EFI_HPC_PADDING_ATTRIBUTES        Attributes;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *NextDescriptors;
+  UINT16                            BusRange;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;
+  BOOLEAN                           BusPadding;
+  UINT32                            TempReservedBusNum;
+
+  PciRootBridgeIo = Bridge->PciRootBridgeIo;
+  SecondBus       = 0;
+  Register        = 0;
+  State           = 0;
+  Attributes      = (EFI_HPC_PADDING_ATTRIBUTES) 0;
+  BusRange        = 0;
+  BusPadding      = FALSE;
+  PciDevice       = NULL;
+  PciAddress      = 0;
+
+  for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+    TempReservedBusNum = 0;
+    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+
+      //
+      // Check to see whether a pci device is present
+      //
+      Status = PciDevicePresent (
+                PciRootBridgeIo,
+                &Pci,
+                StartBusNumber,
+                Device,
+                Func
+                );
+
+      if (EFI_ERROR (Status) && Func == 0) {
+        //
+        // go to next device if there is no Function 0
+        //
+        break;
+      }
+
+      if (EFI_ERROR (Status)) {
+        continue;
+      }
+
+      //
+      // Get the PCI device information
+      //
+      Status = PciSearchDevice (
+                Bridge,
+                &Pci,
+                StartBusNumber,
+                Device,
+                Func,
+                &PciDevice
+                );
+
+      if (EFI_ERROR (Status)) {
+        continue;
+      }
+
+      PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);
+
+      if (!IS_PCI_BRIDGE (&Pci)) {
+        //
+        // PCI bridges will be called later
+        // Here just need for PCI device or PCI to cardbus controller
+        // EfiPciBeforeChildBusEnumeration for PCI Device Node
+        //
+        PreprocessController (
+            PciDevice,
+            PciDevice->BusNumber,
+            PciDevice->DeviceNumber,
+            PciDevice->FunctionNumber,
+            EfiPciBeforeChildBusEnumeration
+            );
+      }
+
+      if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+        //
+        // For Pci Hotplug controller devcie only
+        //
+        if (gPciHotPlugInit != NULL) {
+          //
+          // Check if it is a Hotplug PCI controller
+          //
+          if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {
+            gPciRootHpcData[HpIndex].Found = TRUE;
+
+            if (!gPciRootHpcData[HpIndex].Initialized) {
+
+              Status = CreateEventForHpc (HpIndex, &Event);
+
+              ASSERT (!EFI_ERROR (Status));
+
+              Status = gPciHotPlugInit->InitializeRootHpc (
+                                          gPciHotPlugInit,
+                                          gPciRootHpcPool[HpIndex].HpcDevicePath,
+                                          PciAddress,
+                                          Event,
+                                          &State
+                                          );
+
+              PreprocessController (
+                PciDevice,
+                PciDevice->BusNumber,
+                PciDevice->DeviceNumber,
+                PciDevice->FunctionNumber,
+                EfiPciBeforeChildBusEnumeration
+              );
+            }
+          }
+        }
+      }
+
+      if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {
+        //
+        // For PPB
+        //
+        if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+          //
+          // If Hot Plug is supported,
+          // Get the bridge information
+          //
+          BusPadding = FALSE;
+          if (gPciHotPlugInit != NULL) {
+
+            if (IsPciHotPlugBus (PciDevice)) {
+
+              //
+              // If it is initialized, get the padded bus range
+              //
+              Status = gPciHotPlugInit->GetResourcePadding (
+                                          gPciHotPlugInit,
+                                          PciDevice->DevicePath,
+                                          PciAddress,
+                                          &State,
+                                          (VOID **) &Descriptors,
+                                          &Attributes
+                                          );
+
+              if (EFI_ERROR (Status)) {
+                return Status;
+              }
+
+              BusRange = 0;
+              NextDescriptors = Descriptors;
+              Status = PciGetBusRange (
+                        &NextDescriptors,
+                        NULL,
+                        NULL,
+                        &BusRange
+                        );
+
+              FreePool (Descriptors);
+
+              if (!EFI_ERROR (Status)) {
+                BusPadding = TRUE;
+              } else if (Status != EFI_NOT_FOUND) {
+                //
+                // EFI_NOT_FOUND is not a real error. It indicates no bus number padding requested.
+                //
+                return Status;
+              }
+            }
+          }
+        }
+
+        Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);
+        if (EFI_ERROR (Status)) {
+          return Status;
+        }
+        SecondBus = *SubBusNumber;
+
+        Register  = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
+        Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);
+
+        Status = PciRootBridgeIo->Pci.Write (
+                                        PciRootBridgeIo,
+                                        EfiPciWidthUint16,
+                                        Address,
+                                        1,
+                                        &Register
+                                        );
+
+
+        //
+        // If it is PPB, resursively search down this bridge
+        //
+        if (IS_PCI_BRIDGE (&Pci)) {
+
+          //
+          // Temporarily initialize SubBusNumber to maximum bus number to ensure the
+          // PCI configuration transaction to go through any PPB
+          //
+          Register  = PciGetMaxBusNumber (Bridge);
+          Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
+          Status = PciRootBridgeIo->Pci.Write (
+                                          PciRootBridgeIo,
+                                          EfiPciWidthUint8,
+                                          Address,
+                                          1,
+                                          &Register
+                                          );
+
+          //
+          // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
+          //
+          PreprocessController (
+            PciDevice,
+            PciDevice->BusNumber,
+            PciDevice->DeviceNumber,
+            PciDevice->FunctionNumber,
+            EfiPciBeforeChildBusEnumeration
+            );
+
+          Status = PciScanBus (
+                    PciDevice,
+                    SecondBus,
+                    SubBusNumber,
+                    PaddedBusRange
+                    );
+          if (EFI_ERROR (Status)) {
+            return Status;
+          }
+        }
+
+        if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding) {
+          //
+          // Ensure the device is enabled and initialized
+          //
+          if ((Attributes == EfiPaddingPciRootBridge) &&
+              (State & EFI_HPC_STATE_ENABLED) != 0    &&
+              (State & EFI_HPC_STATE_INITIALIZED) != 0) {
+            *PaddedBusRange = (UINT8) ((UINT8) (BusRange) + *PaddedBusRange);
+          } else {
+            //
+            // Reserve the larger one between the actual occupied bus number and padded bus number
+            //
+            Status = PciAllocateBusNumber (PciDevice, SecondBus, (UINT8) (BusRange), &PaddedSubBus);
+            if (EFI_ERROR (Status)) {
+              return Status;
+            }
+            *SubBusNumber = MAX (PaddedSubBus, *SubBusNumber);
+          }
+        }
+
+        //
+        // Set the current maximum bus number under the PPB
+        //
+        Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
+
+        Status = PciRootBridgeIo->Pci.Write (
+                                        PciRootBridgeIo,
+                                        EfiPciWidthUint8,
+                                        Address,
+                                        1,
+                                        SubBusNumber
+                                        );
+      } else  {
+        //
+        // It is device. Check PCI IOV for Bus reservation
+        // Go through each function, just reserve the MAX ReservedBusNum for one device
+        //
+        if (PcdGetBool (PcdSrIovSupport) && PciDevice->SrIovCapabilityOffset != 0) {
+          if (TempReservedBusNum < PciDevice->ReservedBusNum) {
+
+            Status = PciAllocateBusNumber (PciDevice, *SubBusNumber, (UINT8) (PciDevice->ReservedBusNum - TempReservedBusNum), SubBusNumber);
+            if (EFI_ERROR (Status)) {
+              return Status;
+            }
+            TempReservedBusNum = PciDevice->ReservedBusNum;
+
+            if (Func == 0) {
+              DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));
+            } else {
+              DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));
+            }
+          }
+        }
+      }
+
+      if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
+
+        //
+        // Skip sub functions, this is not a multi function device
+        //
+
+        Func = PCI_MAX_FUNC;
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Process Option Rom on the specified root bridge.
+
+  @param Bridge  Pci root bridge device instance.
+
+  @retval EFI_SUCCESS   Success process.
+  @retval other         Some error occurred when processing Option Rom on the root bridge.
+
+**/
+EFI_STATUS
+PciRootBridgeP2CProcess (
+  IN PCI_IO_DEVICE *Bridge
+  )
+{
+  LIST_ENTRY      *CurrentLink;
+  PCI_IO_DEVICE   *Temp;
+  EFI_HPC_STATE   State;
+  UINT64          PciAddress;
+  EFI_STATUS      Status;
+
+  CurrentLink = Bridge->ChildList.ForwardLink;
+
+  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
+
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
+
+      if (gPciHotPlugInit != NULL && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+
+        //
+        // Raise the EFI_IOB_PCI_HPC_INIT status code
+        //
+        REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+          EFI_PROGRESS_CODE,
+          EFI_IO_BUS_PCI | EFI_IOB_PCI_HPC_INIT,
+          Temp->DevicePath
+          );
+
+        PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);
+        Status = gPciHotPlugInit->InitializeRootHpc (
+                                    gPciHotPlugInit,
+                                    Temp->DevicePath,
+                                    PciAddress,
+                                    NULL,
+                                    &State
+                                    );
+
+        if (!EFI_ERROR (Status)) {
+          Status = PciBridgeEnumerator (Temp);
+
+          if (EFI_ERROR (Status)) {
+            return Status;
+          }
+        }
+
+        CurrentLink = CurrentLink->ForwardLink;
+        continue;
+
+      }
+    }
+
+    if (!IsListEmpty (&Temp->ChildList)) {
+      Status = PciRootBridgeP2CProcess (Temp);
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Process Option Rom on the specified host bridge.
+
+  @param PciResAlloc    Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
+
+  @retval EFI_SUCCESS   Success process.
+  @retval EFI_NOT_FOUND Can not find the root bridge instance.
+  @retval other         Some error occurred when processing Option Rom on the host bridge.
+
+**/
+EFI_STATUS
+PciHostBridgeP2CProcess (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+  )
+{
+  EFI_HANDLE    RootBridgeHandle;
+  PCI_IO_DEVICE *RootBridgeDev;
+  EFI_STATUS    Status;
+
+  if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+    return EFI_SUCCESS;
+  }
+
+  RootBridgeHandle = NULL;
+
+  while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+    //
+    // Get RootBridg Device by handle
+    //
+    RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+
+    if (RootBridgeDev == NULL) {
+      return EFI_NOT_FOUND;
+    }
+
+    Status = PciRootBridgeP2CProcess (RootBridgeDev);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function is used to enumerate the entire host bridge
+  in a given platform.
+
+  @param PciResAlloc   A pointer to the PCI Host Resource Allocation protocol.
+
+  @retval EFI_SUCCESS            Successfully enumerated the host bridge.
+  @retval EFI_OUT_OF_RESOURCES   No enough memory available.
+  @retval other                  Some error occurred when enumerating the host bridge.
+
+**/
+EFI_STATUS
+PciHostBridgeEnumerator (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc
+  )
+{
+  EFI_HANDLE                        RootBridgeHandle;
+  PCI_IO_DEVICE                     *RootBridgeDev;
+  EFI_STATUS                        Status;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;
+  UINT16                            MinBus;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
+  UINT8                             StartBusNumber;
+  LIST_ENTRY                        RootBridgeList;
+  LIST_ENTRY                        *Link;
+
+  if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+    InitializeHotPlugSupport ();
+  }
+
+  InitializeListHead (&RootBridgeList);
+
+  //
+  // Notify the bus allocation phase is about to start
+  //
+  Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n"));
+  RootBridgeHandle = NULL;
+  while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+    //
+    // if a root bridge instance is found, create root bridge device for it
+    //
+
+    RootBridgeDev = CreateRootBridge (RootBridgeHandle);
+
+    if (RootBridgeDev == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    //
+    // Enumerate all the buses under this root bridge
+    //
+    Status = PciRootBridgeEnumerator (
+              PciResAlloc,
+              RootBridgeDev
+              );
+
+    if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+      InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));
+    } else {
+      DestroyRootBridge (RootBridgeDev);
+    }
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  //
+  // Notify the bus allocation phase is finished for the first time
+  //
+  NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
+
+  if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+    //
+    // Reset all assigned PCI bus number in all PPB
+    //
+    RootBridgeHandle = NULL;
+    Link = GetFirstNode (&RootBridgeList);
+    while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&
+      (!IsNull (&RootBridgeList, Link))) {
+      RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);
+      //
+      // Get the Bus information
+      //
+      Status = PciResAlloc->StartBusEnumeration (
+                              PciResAlloc,
+                              RootBridgeHandle,
+                              (VOID **) &Configuration
+                              );
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      //
+      // Get the bus number to start with
+      //
+      StartBusNumber  = (UINT8) (Configuration->AddrRangeMin);
+
+      ResetAllPpbBusNumber (
+        RootBridgeDev,
+        StartBusNumber
+      );
+
+      FreePool (Configuration);
+      Link = RemoveEntryList (Link);
+      DestroyRootBridge (RootBridgeDev);
+    }
+
+    //
+    // Wait for all HPC initialized
+    //
+    Status = AllRootHPCInitialized (STALL_1_SECOND * 15);
+
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "Some root HPC failed to initialize\n"));
+      return Status;
+    }
+
+    //
+    // Notify the bus allocation phase is about to start for the 2nd time
+    //
+    Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
+
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n"));
+    RootBridgeHandle = NULL;
+    while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+      //
+      // if a root bridge instance is found, create root bridge device for it
+      //
+      RootBridgeDev = CreateRootBridge (RootBridgeHandle);
+
+      if (RootBridgeDev == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      //
+      // Enumerate all the buses under this root bridge
+      //
+      Status = PciRootBridgeEnumerator (
+                PciResAlloc,
+                RootBridgeDev
+                );
+
+      DestroyRootBridge (RootBridgeDev);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+    }
+
+    //
+    // Notify the bus allocation phase is to end for the 2nd time
+    //
+    NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
+  }
+
+  //
+  // Notify the resource allocation phase is to start
+  //
+  Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  RootBridgeHandle = NULL;
+  while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+    //
+    // if a root bridge instance is found, create root bridge device for it
+    //
+    RootBridgeDev = CreateRootBridge (RootBridgeHandle);
+
+    if (RootBridgeDev == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    Status = StartManagingRootBridge (RootBridgeDev);
+
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;
+    Status          = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
+
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);
+
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    //
+    // Determine root bridge attribute by calling interface of Pcihostbridge
+    // protocol
+    //
+    DetermineRootBridgeAttributes (
+      PciResAlloc,
+      RootBridgeDev
+      );
+
+    //
+    // Collect all the resource information under this root bridge
+    // A database that records all the information about pci device subject to this
+    // root bridge will then be created
+    //
+    Status = PciPciDeviceInfoCollector (
+              RootBridgeDev,
+              (UINT8) MinBus
+              );
+
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    InsertRootBridge (RootBridgeDev);
+
+    //
+    // Record the hostbridge handle
+    //
+    AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function is used to program the Resizable BAR Register.
+
+  @param PciIoDevice            A pointer to the PCI_IO_DEVICE.
+  @param ResizableBarOp         PciResizableBarMax: Set BAR to max size
+                                PciResizableBarMin: set BAR to min size.
+
+  @retval EFI_SUCCESS           Successfully enumerated the host bridge.
+  @retval other                 Some error occurred when enumerating the host bridge.
+
+**/
+EFI_STATUS
+PciProgramResizableBar (
+  IN PCI_IO_DEVICE                *PciIoDevice,
+  IN PCI_RESIZABLE_BAR_OPERATION  ResizableBarOp
+  )
+{
+  EFI_PCI_IO_PROTOCOL  *PciIo;
+  UINT64                Capabilities;
+  UINT32                Index;
+  UINT32                Offset;
+  INTN                  Bit;
+  UINTN                 ResizableBarNumber;
+  EFI_STATUS            Status;
+  PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY   Entries[PCI_MAX_BAR];
+
+  ASSERT (PciIoDevice->ResizableBarOffset != 0);
+
+  DEBUG ((DEBUG_INFO, "   Programs Resizable BAR register, offset: 0x%08x, number: %d\n",
+        PciIoDevice->ResizableBarOffset, PciIoDevice->ResizableBarNumber));
+
+  ResizableBarNumber = MIN (PciIoDevice->ResizableBarNumber, PCI_MAX_BAR);
+  PciIo = &PciIoDevice->PciIo;
+  Status = PciIo->Pci.Read (
+          PciIo,
+          EfiPciIoWidthUint8,
+          PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER),
+          sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY) * ResizableBarNumber,
+          (VOID *)(&Entries)
+          );
+  ASSERT_EFI_ERROR (Status);
+
+  for (Index = 0; Index < ResizableBarNumber; Index++) {
+
+    //
+    // When the bit of Capabilities Set, indicates that the Function supports
+    // operating with the BAR sized to (2^Bit) MB.
+    // Example:
+    // Bit 0 is set: supports operating with the BAR sized to 1 MB
+    // Bit 1 is set: supports operating with the BAR sized to 2 MB
+    // Bit n is set: supports operating with the BAR sized to (2^n) MB
+    //
+    Capabilities = LShiftU64(Entries[Index].ResizableBarControl.Bits.BarSizeCapability, 28)
+                  | Entries[Index].ResizableBarCapability.Bits.BarSizeCapability;
+
+    if (ResizableBarOp == PciResizableBarMax) {
+      Bit = HighBitSet64(Capabilities);
+    } else {
+      ASSERT (ResizableBarOp == PciResizableBarMin);
+      Bit = LowBitSet64(Capabilities);
+    }
+
+    ASSERT (Bit >= 0);
+
+    Offset = PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER)
+            + Index * sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY)
+            + OFFSET_OF (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY, ResizableBarControl);
+
+    Entries[Index].ResizableBarControl.Bits.BarSize = (UINT32) Bit;
+    DEBUG ((
+      DEBUG_INFO,
+      "   Resizable Bar: Offset = 0x%x, Bar Size Capability = 0x%016lx, New Bar Size = 0x%lx\n",
+      OFFSET_OF (PCI_TYPE00, Device.Bar[Entries[Index].ResizableBarControl.Bits.BarIndex]),
+      Capabilities, LShiftU64 (SIZE_1MB, Bit)
+      ));
+    PciIo->Pci.Write (
+            PciIo,
+            EfiPciIoWidthUint32,
+            Offset,
+            1,
+            &Entries[Index].ResizableBarControl.Uint32
+            );
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h
new file mode 100644
index 0000000000..70ab07a8c3
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h
@@ -0,0 +1,179 @@
+/** @file
+  Internal library declaration for PCI Bus module.
+
+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_PCI_LIB_H_
+#define _EFI_PCI_LIB_H_
+
+
+typedef struct {
+  EFI_HANDLE            Handle;
+} EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD;
+
+typedef struct {
+  UINT32                             Bar;
+  UINT16                             DevicePathSize;
+  UINT16                             ReqResSize;
+  UINT16                             AllocResSize;
+  UINT8                              *DevicePath;
+  UINT8                              *ReqRes;
+  UINT8                              *AllocRes;
+} EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD;
+
+typedef enum {
+  PciResizableBarMin = 0x00,
+  PciResizableBarMax = 0xFF
+} PCI_RESIZABLE_BAR_OPERATION;
+
+/**
+  Retrieve the PCI Card device BAR information via PciIo interface.
+
+  @param PciIoDevice        PCI Card device instance.
+
+**/
+VOID
+GetBackPcCardBar (
+  IN  PCI_IO_DEVICE                  *PciIoDevice
+  );
+
+/**
+  Remove rejected pci device from specific root bridge
+  handle.
+
+  @param RootBridgeHandle  Specific parent root bridge handle.
+  @param Bridge            Bridge device instance.
+
+**/
+VOID
+RemoveRejectedPciDevices (
+  IN EFI_HANDLE        RootBridgeHandle,
+  IN PCI_IO_DEVICE     *Bridge
+  );
+
+/**
+  Submits the I/O and memory resource requirements for the specified PCI Host Bridge.
+
+  @param PciResAlloc  Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
+
+  @retval EFI_SUCCESS           Successfully finished resource allocation.
+  @retval EFI_NOT_FOUND         Cannot get root bridge instance.
+  @retval EFI_OUT_OF_RESOURCES  Platform failed to program the resources if no hot plug supported.
+  @retval other                 Some error occurred when allocating resources for the PCI Host Bridge.
+
+  @note   Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
+
+**/
+EFI_STATUS
+PciHostBridgeResourceAllocator (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+  );
+
+/**
+  Allocate NumberOfBuses buses and return the next available PCI bus number.
+
+  @param  Bridge           Bridge device instance.
+  @param  StartBusNumber   Current available PCI bus number.
+  @param  NumberOfBuses    Number of buses enumerated below the StartBusNumber.
+  @param  NextBusNumber    Next available PCI bus number.
+
+  @retval EFI_SUCCESS           Available bus number resource is enough. Next available PCI bus number
+                                is returned in NextBusNumber.
+  @retval EFI_OUT_OF_RESOURCES  Available bus number resource is not enough for allocation.
+
+**/
+EFI_STATUS
+PciAllocateBusNumber (
+  IN PCI_IO_DEVICE                      *Bridge,
+  IN UINT8                              StartBusNumber,
+  IN UINT8                              NumberOfBuses,
+  OUT UINT8                             *NextBusNumber
+  );
+
+/**
+  Scan pci bus and assign bus number to the given PCI bus system.
+
+  @param  Bridge           Bridge device instance.
+  @param  StartBusNumber   start point.
+  @param  SubBusNumber     Point to sub bus number.
+  @param  PaddedBusRange   Customized bus number.
+
+  @retval EFI_SUCCESS      Successfully scanned and assigned bus number.
+  @retval other            Some error occurred when scanning pci bus.
+
+  @note   Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
+
+**/
+EFI_STATUS
+PciScanBus (
+  IN PCI_IO_DEVICE                      *Bridge,
+  IN UINT8                              StartBusNumber,
+  OUT UINT8                             *SubBusNumber,
+  OUT UINT8                             *PaddedBusRange
+  );
+
+/**
+  Process Option Rom on the specified root bridge.
+
+  @param Bridge  Pci root bridge device instance.
+
+  @retval EFI_SUCCESS   Success process.
+  @retval other         Some error occurred when processing Option Rom on the root bridge.
+
+**/
+EFI_STATUS
+PciRootBridgeP2CProcess (
+  IN PCI_IO_DEVICE *Bridge
+  );
+
+/**
+  Process Option Rom on the specified host bridge.
+
+  @param PciResAlloc    Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
+
+  @retval EFI_SUCCESS   Success process.
+  @retval EFI_NOT_FOUND Can not find the root bridge instance.
+  @retval other         Some error occurred when processing Option Rom on the host bridge.
+
+**/
+EFI_STATUS
+PciHostBridgeP2CProcess (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+  );
+
+/**
+  This function is used to enumerate the entire host bridge
+  in a given platform.
+
+  @param PciResAlloc   A pointer to the PCI Host Resource Allocation protocol.
+
+  @retval EFI_SUCCESS            Successfully enumerated the host bridge.
+  @retval EFI_OUT_OF_RESOURCES   No enough memory available.
+  @retval other                  Some error occurred when enumerating the host bridge.
+
+**/
+EFI_STATUS
+PciHostBridgeEnumerator (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc
+  );
+
+/**
+  This function is used to program the Resizable BAR Register.
+
+  @param PciIoDevice            A pointer to the PCI_IO_DEVICE.
+  @param ResizableBarOp         PciResizableBarMax: Set BAR to max size
+                                PciResizableBarMin: set BAR to min size.
+
+  @retval EFI_SUCCESS           Successfully enumerated the host bridge.
+  @retval other                 Some error occurred when enumerating the host bridge.
+
+**/
+EFI_STATUS
+PciProgramResizableBar (
+  IN PCI_IO_DEVICE                *PciIoDevice,
+  IN PCI_RESIZABLE_BAR_OPERATION  ResizableBarOp
+  );
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c
new file mode 100644
index 0000000000..efdfa2d415
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c
@@ -0,0 +1,776 @@
+/** @file
+  PCI Rom supporting funtions implementation for PCI Bus module.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2021, American Megatrends International LLC.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+
+/**
+  Load the EFI Image from Option ROM
+
+  @param PciIoDevice   PCI IO device instance.
+  @param FilePath      The file path of the EFI Image
+  @param BufferSize    On input the size of Buffer in bytes. On output with a return
+                       code of EFI_SUCCESS, the amount of data transferred to Buffer.
+                       On output with a return code of EFI_BUFFER_TOO_SMALL,
+                       the size of Buffer required to retrieve the requested file.
+  @param Buffer        The memory buffer to transfer the file to. If Buffer is NULL,
+                       then no the size of the requested file is returned in BufferSize.
+
+  @retval EFI_SUCCESS           The file was loaded.
+  @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or
+                                BufferSize is NULL.
+  @retval EFI_NOT_FOUND         Not found PCI Option Rom on PCI device.
+  @retval EFI_DEVICE_ERROR      Failed to decompress PCI Option Rom image.
+  @retval EFI_BUFFER_TOO_SMALL  The BufferSize is too small to read the current directory entry.
+                                BufferSize has been updated with the size needed to complete the request.
+**/
+EFI_STATUS
+LocalLoadFile2 (
+  IN PCI_IO_DEVICE            *PciIoDevice,
+  IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+  IN OUT UINTN                *BufferSize,
+  IN VOID                     *Buffer      OPTIONAL
+  )
+{
+  EFI_STATUS                                Status;
+  MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH   *EfiOpRomImageNode;
+  EFI_PCI_EXPANSION_ROM_HEADER              *EfiRomHeader;
+  PCI_DATA_STRUCTURE                        *Pcir;
+  UINT32                                    ImageSize;
+  UINT8                                     *ImageBuffer;
+  UINT32                                    ImageLength;
+  UINT32                                    DestinationSize;
+  UINT32                                    ScratchSize;
+  VOID                                      *Scratch;
+  EFI_DECOMPRESS_PROTOCOL                   *Decompress;
+  UINT32                                    InitializationSize;
+
+  EfiOpRomImageNode = (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *) FilePath;
+  if ((EfiOpRomImageNode == NULL) ||
+      (DevicePathType (FilePath) != MEDIA_DEVICE_PATH) ||
+      (DevicePathSubType (FilePath) != MEDIA_RELATIVE_OFFSET_RANGE_DP) ||
+      (DevicePathNodeLength (FilePath) != sizeof (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH)) ||
+      (!IsDevicePathEnd (NextDevicePathNode (FilePath))) ||
+      (EfiOpRomImageNode->StartingOffset > EfiOpRomImageNode->EndingOffset) ||
+      (EfiOpRomImageNode->EndingOffset >= PciIoDevice->RomSize) ||
+      (BufferSize == NULL)
+      ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (
+      (UINT8 *) PciIoDevice->PciIo.RomImage + EfiOpRomImageNode->StartingOffset
+      );
+  if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
+    return EFI_NOT_FOUND;
+  }
+
+
+  Pcir = (PCI_DATA_STRUCTURE *) ((UINT8 *) EfiRomHeader + EfiRomHeader->PcirOffset);
+  ASSERT (Pcir->Signature == PCI_DATA_STRUCTURE_SIGNATURE);
+
+  if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
+      (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&
+      ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
+       (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) &&
+      (EfiRomHeader->CompressionType <= EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED)
+       ) {
+
+    ImageSize = Pcir->ImageLength * 512;
+    InitializationSize = (UINT32) EfiRomHeader->InitializationSize * 512;
+    if (InitializationSize > ImageSize || EfiRomHeader->EfiImageHeaderOffset >=  InitializationSize) {
+      return EFI_NOT_FOUND;
+    }
+
+    ImageBuffer             = (UINT8 *) EfiRomHeader + EfiRomHeader->EfiImageHeaderOffset;
+    ImageLength             = InitializationSize - EfiRomHeader->EfiImageHeaderOffset;
+
+    if (EfiRomHeader->CompressionType != EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
+      //
+      // Uncompressed: Copy the EFI Image directly to user's buffer
+      //
+      if (Buffer == NULL || *BufferSize < ImageLength) {
+        *BufferSize = ImageLength;
+        return EFI_BUFFER_TOO_SMALL;
+      }
+
+      *BufferSize = ImageLength;
+      CopyMem (Buffer, ImageBuffer, ImageLength);
+      return EFI_SUCCESS;
+
+    } else {
+      //
+      // Compressed: Uncompress before copying
+      //
+      Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
+      if (EFI_ERROR (Status)) {
+        return EFI_DEVICE_ERROR;
+      }
+      Status = Decompress->GetInfo (
+                             Decompress,
+                             ImageBuffer,
+                             ImageLength,
+                             &DestinationSize,
+                             &ScratchSize
+                             );
+      if (EFI_ERROR (Status)) {
+        return EFI_DEVICE_ERROR;
+      }
+
+      if (Buffer == NULL || *BufferSize < DestinationSize) {
+        *BufferSize = DestinationSize;
+        return EFI_BUFFER_TOO_SMALL;
+      }
+
+      *BufferSize = DestinationSize;
+      Scratch = AllocatePool (ScratchSize);
+      if (Scratch == NULL) {
+        return EFI_DEVICE_ERROR;
+      }
+
+      Status = Decompress->Decompress (
+                             Decompress,
+                             ImageBuffer,
+                             ImageLength,
+                             Buffer,
+                             DestinationSize,
+                             Scratch,
+                             ScratchSize
+                             );
+      FreePool (Scratch);
+
+      if (EFI_ERROR (Status)) {
+        return EFI_DEVICE_ERROR;
+      }
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Initialize a PCI LoadFile2 instance.
+
+  @param PciIoDevice   PCI IO Device.
+
+**/
+VOID
+InitializePciLoadFile2 (
+  IN PCI_IO_DEVICE       *PciIoDevice
+  )
+{
+  PciIoDevice->LoadFile2.LoadFile = LoadFile2;
+}
+
+/**
+  Causes the driver to load a specified file.
+
+  @param This        Indicates a pointer to the calling context.
+  @param FilePath    The device specific path of the file to load.
+  @param BootPolicy  Should always be FALSE.
+  @param BufferSize  On input the size of Buffer in bytes. On output with a return
+                     code of EFI_SUCCESS, the amount of data transferred to Buffer.
+                     On output with a return code of EFI_BUFFER_TOO_SMALL,
+                     the size of Buffer required to retrieve the requested file.
+  @param Buffer      The memory buffer to transfer the file to. If Buffer is NULL,
+                     then no the size of the requested file is returned in BufferSize.
+
+  @retval EFI_SUCCESS           The file was loaded.
+  @retval EFI_UNSUPPORTED       BootPolicy is TRUE.
+  @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or
+                                BufferSize is NULL.
+  @retval EFI_NOT_FOUND         Not found PCI Option Rom on PCI device.
+  @retval EFI_DEVICE_ERROR      Failed to decompress PCI Option Rom image.
+  @retval EFI_BUFFER_TOO_SMALL  The BufferSize is too small to read the current directory entry.
+                                BufferSize has been updated with the size needed to complete the request.
+
+**/
+EFI_STATUS
+EFIAPI
+LoadFile2 (
+  IN EFI_LOAD_FILE2_PROTOCOL  *This,
+  IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+  IN BOOLEAN                  BootPolicy,
+  IN OUT UINTN                *BufferSize,
+  IN VOID                     *Buffer      OPTIONAL
+  )
+{
+  PCI_IO_DEVICE                             *PciIoDevice;
+
+  if (BootPolicy) {
+    return EFI_UNSUPPORTED;
+  }
+  PciIoDevice = PCI_IO_DEVICE_FROM_LOAD_FILE2_THIS (This);
+
+  return LocalLoadFile2 (
+           PciIoDevice,
+           FilePath,
+           BufferSize,
+           Buffer
+           );
+}
+
+/**
+  Get Pci device's oprom information.
+
+  @param PciIoDevice    Input Pci device instance.
+                        Output Pci device instance with updated OptionRom size.
+
+  @retval EFI_NOT_FOUND Pci device has not Option Rom.
+  @retval EFI_SUCCESS   Pci device has Option Rom.
+
+**/
+EFI_STATUS
+GetOpRomInfo (
+  IN OUT PCI_IO_DEVICE    *PciIoDevice
+  )
+{
+  UINT8                           RomBarIndex;
+  UINT32                          AllOnes;
+  UINT64                          Address;
+  EFI_STATUS                      Status;
+  UINT8                           Bus;
+  UINT8                           Device;
+  UINT8                           Function;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+  Bus             = PciIoDevice->BusNumber;
+  Device          = PciIoDevice->DeviceNumber;
+  Function        = PciIoDevice->FunctionNumber;
+
+  PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;
+
+  //
+  // Offset is 0x30 if is not ppb
+  //
+
+  //
+  // 0x30
+  //
+  RomBarIndex = PCI_EXPANSION_ROM_BASE;
+
+  if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
+    //
+    // If is ppb, 0x38
+    //
+    RomBarIndex = PCI_BRIDGE_ROMBAR;
+  }
+  //
+  // The bit0 is 0 to prevent the enabling of the Rom address decoder
+  //
+  AllOnes = 0xfffffffe;
+  Address = EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex);
+
+  Status = PciRootBridgeIo->Pci.Write (
+                                  PciRootBridgeIo,
+                                  EfiPciWidthUint32,
+                                  Address,
+                                  1,
+                                  &AllOnes
+                                  );
+  if (EFI_ERROR (Status)) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Read back
+  //
+  Status = PciRootBridgeIo->Pci.Read(
+                                  PciRootBridgeIo,
+                                  EfiPciWidthUint32,
+                                  Address,
+                                  1,
+                                  &AllOnes
+                                  );
+  if (EFI_ERROR (Status)) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Bits [1, 10] are reserved
+  //
+  AllOnes &= 0xFFFFF800;
+  if ((AllOnes == 0) || (AllOnes == 0xFFFFF800)) {
+    return EFI_NOT_FOUND;
+  }
+
+  PciIoDevice->RomSize = (~AllOnes) + 1;
+  return EFI_SUCCESS;
+}
+
+/**
+  Check if the RomImage contains EFI Images.
+
+  @param  RomImage  The ROM address of Image for check.
+  @param  RomSize   Size of ROM for check.
+
+  @retval TRUE     ROM contain EFI Image.
+  @retval FALSE    ROM not contain EFI Image.
+
+**/
+BOOLEAN
+ContainEfiImage (
+  IN VOID            *RomImage,
+  IN UINT64          RomSize
+  )
+{
+  PCI_EXPANSION_ROM_HEADER  *RomHeader;
+  PCI_DATA_STRUCTURE        *RomPcir;
+  UINT8                     Indicator;
+
+  Indicator = 0;
+  RomHeader = RomImage;
+  if (RomHeader == NULL) {
+    return FALSE;
+  }
+
+  do {
+    if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
+      RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + 512);
+      continue;
+    }
+
+    //
+    // The PCI Data Structure must be DWORD aligned.
+    //
+    if (RomHeader->PcirOffset == 0 ||
+        (RomHeader->PcirOffset & 3) != 0 ||
+        (UINT8 *) RomHeader + RomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > (UINT8 *) RomImage + RomSize) {
+      break;
+    }
+
+    RomPcir = (PCI_DATA_STRUCTURE *) ((UINT8 *) RomHeader + RomHeader->PcirOffset);
+    if (RomPcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
+      break;
+    }
+
+    if (RomPcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) {
+      return TRUE;
+    }
+
+    Indicator = RomPcir->Indicator;
+    RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + RomPcir->ImageLength * 512);
+  } while (((UINT8 *) RomHeader < (UINT8 *) RomImage + RomSize) && ((Indicator & 0x80) == 0x00));
+
+  return FALSE;
+}
+
+/**
+  Load Option Rom image for specified PCI device.
+
+  @param PciDevice Pci device instance.
+  @param RomBase   Base address of Option Rom.
+
+  @retval EFI_OUT_OF_RESOURCES No enough memory to hold image.
+  @retval EFI_SUCESS           Successfully loaded Option Rom.
+
+**/
+EFI_STATUS
+LoadOpRomImage (
+  IN PCI_IO_DEVICE   *PciDevice,
+  IN UINT64          RomBase
+  )
+{
+  UINT8                     RomBarIndex;
+  UINT8                     Indicator;
+  UINT16                    OffsetPcir;
+  UINT32                    RomBarOffset;
+  UINT32                    RomBar;
+  EFI_STATUS                RetStatus;
+  BOOLEAN                   FirstCheck;
+  UINT8                     *Image;
+  PCI_EXPANSION_ROM_HEADER  *RomHeader;
+  PCI_DATA_STRUCTURE        *RomPcir;
+  UINT64                    RomSize;
+  UINT64                    RomImageSize;
+  UINT32                    LegacyImageLength;
+  UINT8                     *RomInMemory;
+  UINT8                     CodeType;
+
+  RomSize       = PciDevice->RomSize;
+
+  Indicator     = 0;
+  RomImageSize  = 0;
+  RomInMemory   = NULL;
+  CodeType      = 0xFF;
+
+  //
+  // Get the RomBarIndex
+  //
+
+  //
+  // 0x30
+  //
+  RomBarIndex = PCI_EXPANSION_ROM_BASE;
+  if (IS_PCI_BRIDGE (&(PciDevice->Pci))) {
+    //
+    // if is ppb
+    //
+
+    //
+    // 0x38
+    //
+    RomBarIndex = PCI_BRIDGE_ROMBAR;
+  }
+  //
+  // Allocate memory for Rom header and PCIR
+  //
+  RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER));
+  if (RomHeader == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));
+  if (RomPcir == NULL) {
+    FreePool (RomHeader);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  RomBar = (UINT32) RomBase;
+
+  //
+  // Enable RomBar
+  //
+  RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);
+
+  RomBarOffset  = RomBar;
+  RetStatus     = EFI_NOT_FOUND;
+  FirstCheck    = TRUE;
+  LegacyImageLength = 0;
+
+  do {
+    PciDevice->PciRootBridgeIo->Mem.Read (
+                                      PciDevice->PciRootBridgeIo,
+                                      EfiPciWidthUint8,
+                                      RomBarOffset,
+                                      sizeof (PCI_EXPANSION_ROM_HEADER),
+                                      (UINT8 *) RomHeader
+                                      );
+
+    if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
+      RomBarOffset = RomBarOffset + 512;
+      if (FirstCheck) {
+        break;
+      } else {
+        RomImageSize = RomImageSize + 512;
+        continue;
+      }
+    }
+
+    FirstCheck  = FALSE;
+    OffsetPcir  = RomHeader->PcirOffset;
+    //
+    // If the pointer to the PCI Data Structure is invalid, no further images can be located.
+    // The PCI Data Structure must be DWORD aligned.
+    //
+    if (OffsetPcir == 0 ||
+        (OffsetPcir & 3) != 0 ||
+        RomImageSize + OffsetPcir + sizeof (PCI_DATA_STRUCTURE) > RomSize) {
+      break;
+    }
+    PciDevice->PciRootBridgeIo->Mem.Read (
+                                      PciDevice->PciRootBridgeIo,
+                                      EfiPciWidthUint8,
+                                      RomBarOffset + OffsetPcir,
+                                      sizeof (PCI_DATA_STRUCTURE),
+                                      (UINT8 *) RomPcir
+                                      );
+    //
+    // If a valid signature is not present in the PCI Data Structure, no further images can be located.
+    //
+    if (RomPcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
+      break;
+    }
+    if (RomImageSize + RomPcir->ImageLength * 512 > RomSize) {
+      break;
+    }
+    if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {
+      CodeType = PCI_CODE_TYPE_PCAT_IMAGE;
+      LegacyImageLength = ((UINT32)((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512) * 512;
+    }
+    Indicator     = RomPcir->Indicator;
+    RomImageSize  = RomImageSize + RomPcir->ImageLength * 512;
+    RomBarOffset  = RomBarOffset + RomPcir->ImageLength * 512;
+  } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < RomSize));
+
+  //
+  // Some Legacy Cards do not report the correct ImageLength so used the maximum
+  // of the legacy length and the PCIR Image Length
+  //
+  if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {
+    RomImageSize = MAX (RomImageSize, LegacyImageLength);
+  }
+
+  if (RomImageSize > 0) {
+    RetStatus = EFI_SUCCESS;
+    Image     = AllocatePool ((UINT32) RomImageSize);
+    if (Image == NULL) {
+      RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);
+      FreePool (RomHeader);
+      FreePool (RomPcir);
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    //
+    // Copy Rom image into memory
+    //
+    PciDevice->PciRootBridgeIo->Mem.Read (
+                                      PciDevice->PciRootBridgeIo,
+                                      EfiPciWidthUint8,
+                                      RomBar,
+                                      (UINT32) RomImageSize,
+                                      Image
+                                      );
+    RomInMemory = Image;
+  }
+
+  RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);
+
+  PciDevice->EmbeddedRom    = TRUE;
+  PciDevice->PciIo.RomSize  = RomImageSize;
+  PciDevice->PciIo.RomImage = RomInMemory;
+
+  //TiogaPass Override START : Skip OPROM - Mellanox card which has SSVID 0x15B3 and SSDID 0x0031
+  if (PciDevice->Pci.Hdr.VendorId == 0x15B3 && PciDevice->Pci.Hdr.DeviceId == 0x1015) {
+    if (PciDevice->Pci.Device.SubsystemVendorID == 0x15B3 && PciDevice->Pci.Device.SubsystemID == 0x0031) {
+      PciDevice->PciIo.RomImage = NULL;
+      PciDevice->PciIo.RomSize = 0;
+      DEBUG((DEBUG_ERROR,"Device_MLX @ [B%X|D%X|F%X], VID=%X, DID=%X SVID=%X, SVDID=%XOverrides ROM file @ %X  size=%X .\n\n",
+             PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber,
+             PciDevice->Pci.Hdr.VendorId, PciDevice->Pci.Hdr.DeviceId, PciDevice->Pci.Device.SubsystemVendorID,PciDevice->Pci.Device.SubsystemID,PciDevice->PciIo.RomImage, PciDevice->PciIo.RomSize));
+    }
+  }
+  //TiogaPass Override END
+
+  // For OpROM read from PCI device:
+  //   Add the Rom Image to internal database for later PCI light enumeration
+  //
+  PciRomAddImageMapping (
+    NULL,
+    PciDevice->PciRootBridgeIo->SegmentNumber,
+    PciDevice->BusNumber,
+    PciDevice->DeviceNumber,
+    PciDevice->FunctionNumber,
+    PciDevice->PciIo.RomImage,
+    PciDevice->PciIo.RomSize
+    );
+
+  //
+  // Free allocated memory
+  //
+  FreePool (RomHeader);
+  FreePool (RomPcir);
+
+  return RetStatus;
+}
+
+/**
+  Enable/Disable Option Rom decode.
+
+  @param PciDevice    Pci device instance.
+  @param RomBarIndex  The BAR index of the standard PCI Configuration header to use as the
+                      base address for resource range. The legal range for this field is 0..5.
+  @param RomBar       Base address of Option Rom.
+  @param Enable       Flag for enable/disable decode.
+
+**/
+VOID
+RomDecode (
+  IN PCI_IO_DEVICE   *PciDevice,
+  IN UINT8           RomBarIndex,
+  IN UINT32          RomBar,
+  IN BOOLEAN         Enable
+  )
+{
+  UINT32              Value32;
+  EFI_PCI_IO_PROTOCOL *PciIo;
+
+  PciIo = &PciDevice->PciIo;
+  if (Enable) {
+
+    //
+    // set the Rom base address: now is hardcode
+    // enable its decoder
+    //
+    Value32 = RomBar | 0x1;
+    PciIo->Pci.Write (
+                 PciIo,
+                 (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,
+                 RomBarIndex,
+                 1,
+                 &Value32
+                 );
+
+    //
+    // Programe all upstream bridge
+    //
+    ProgramUpstreamBridgeForRom (PciDevice, RomBar, TRUE);
+
+    //
+    // Setting the memory space bit in the function's command register
+    //
+    PCI_ENABLE_COMMAND_REGISTER(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);
+
+  } else {
+
+    //
+    // disable command register decode to memory
+    //
+    PCI_DISABLE_COMMAND_REGISTER(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);
+
+    //
+    // Destroy the programmed bar in all the upstream bridge.
+    //
+    ProgramUpstreamBridgeForRom (PciDevice, RomBar, FALSE);
+
+    //
+    // disable rom decode
+    //
+    Value32 = 0xFFFFFFFE;
+    PciIo->Pci.Write (
+                 PciIo,
+                 (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,
+                 RomBarIndex,
+                 1,
+                 &Value32
+                 );
+
+  }
+}
+
+/**
+  Load and start the Option Rom image.
+
+  @param PciDevice       Pci device instance.
+
+  @retval EFI_SUCCESS    Successfully loaded and started PCI Option Rom image.
+  @retval EFI_NOT_FOUND  Failed to process PCI Option Rom image.
+
+**/
+EFI_STATUS
+ProcessOpRomImage (
+  IN  PCI_IO_DEVICE   *PciDevice
+  )
+{
+  UINT8                                    Indicator;
+  UINT32                                   ImageSize;
+  VOID                                     *RomBar;
+  UINT8                                    *RomBarOffset;
+  EFI_HANDLE                               ImageHandle;
+  EFI_STATUS                               Status;
+  EFI_STATUS                               RetStatus;
+  EFI_PCI_EXPANSION_ROM_HEADER             *EfiRomHeader;
+  PCI_DATA_STRUCTURE                       *Pcir;
+  EFI_DEVICE_PATH_PROTOCOL                 *PciOptionRomImageDevicePath;
+  MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH  EfiOpRomImageNode;
+  VOID                                     *Buffer;
+  UINTN                                    BufferSize;
+
+  Indicator = 0;
+
+  //
+  // Get the Address of the Option Rom image
+  //
+  RomBar        = PciDevice->PciIo.RomImage;
+  RomBarOffset  = (UINT8 *) RomBar;
+  RetStatus     = EFI_NOT_FOUND;
+
+  if (RomBar == NULL) {
+    return RetStatus;
+  }
+  ASSERT (((EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset)->Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE);
+
+  do {
+    EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;
+    if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
+      RomBarOffset += 512;
+      continue;
+    }
+
+    Pcir        = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);
+    ASSERT (Pcir->Signature == PCI_DATA_STRUCTURE_SIGNATURE);
+    ImageSize   = (UINT32) (Pcir->ImageLength * 512);
+    Indicator   = Pcir->Indicator;
+
+    //
+    // Skip the image if it is not an EFI PCI Option ROM image
+    //
+    if (Pcir->CodeType != PCI_CODE_TYPE_EFI_IMAGE) {
+      goto NextImage;
+    }
+
+    //
+    // Ignore the EFI PCI Option ROM image if it is an EFI application
+    //
+    if (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
+      goto NextImage;
+    }
+
+    //
+    // Create Pci Option Rom Image device path header
+    //
+    EfiOpRomImageNode.Header.Type     = MEDIA_DEVICE_PATH;
+    EfiOpRomImageNode.Header.SubType  = MEDIA_RELATIVE_OFFSET_RANGE_DP;
+    SetDevicePathNodeLength (&EfiOpRomImageNode.Header, sizeof (EfiOpRomImageNode));
+    EfiOpRomImageNode.StartingOffset  = (UINTN) RomBarOffset - (UINTN) RomBar;
+    EfiOpRomImageNode.EndingOffset    = (UINTN) RomBarOffset + ImageSize - 1 - (UINTN) RomBar;
+
+    PciOptionRomImageDevicePath = AppendDevicePathNode (PciDevice->DevicePath, &EfiOpRomImageNode.Header);
+    ASSERT (PciOptionRomImageDevicePath != NULL);
+
+    //
+    // load image and start image
+    //
+    BufferSize  = 0;
+    Buffer      = NULL;
+    ImageHandle = NULL;
+
+    Status = gBS->LoadImage (
+                    FALSE,
+                    gPciBusDriverBinding.DriverBindingHandle,
+                    PciOptionRomImageDevicePath,
+                    Buffer,
+                    BufferSize,
+                    &ImageHandle
+                    );
+    if (EFI_ERROR (Status)) {
+      //
+      // Record the Option ROM Image device path when LoadImage fails.
+      // PciOverride.GetDriver() will try to look for the Image Handle using the device path later.
+      //
+      AddDriver (PciDevice, NULL, PciOptionRomImageDevicePath);
+    } else {
+      Status = gBS->StartImage (ImageHandle, NULL, NULL);
+      if (!EFI_ERROR (Status)) {
+        //
+        // Record the Option ROM Image Handle
+        //
+        AddDriver (PciDevice, ImageHandle, NULL);
+        PciRomAddImageMapping (
+          ImageHandle,
+          PciDevice->PciRootBridgeIo->SegmentNumber,
+          PciDevice->BusNumber,
+          PciDevice->DeviceNumber,
+          PciDevice->FunctionNumber,
+          PciDevice->PciIo.RomImage,
+          PciDevice->PciIo.RomSize
+          );
+        RetStatus = EFI_SUCCESS;
+      }
+    }
+    FreePool (PciOptionRomImageDevicePath);
+
+NextImage:
+    RomBarOffset += ImageSize;
+
+  } while (((Indicator & 0x80) == 0x00) && (((UINTN) RomBarOffset - (UINTN) RomBar) < PciDevice->RomSize));
+
+  return RetStatus;
+}
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h
new file mode 100644
index 0000000000..60e147a7b9
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h
@@ -0,0 +1,136 @@
+/** @file
+  PCI Rom supporting functions declaration for PCI Bus module.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_PCI_OPTION_ROM_SUPPORT_H_
+#define _EFI_PCI_OPTION_ROM_SUPPORT_H_
+
+
+/**
+  Initialize a PCI LoadFile2 instance.
+
+  @param PciIoDevice   PCI IO Device.
+
+**/
+VOID
+InitializePciLoadFile2 (
+  IN PCI_IO_DEVICE       *PciIoDevice
+  );
+
+/**
+  Causes the driver to load a specified file.
+
+  @param This        Indicates a pointer to the calling context.
+  @param FilePath    The device specific path of the file to load.
+  @param BootPolicy  Should always be FALSE.
+  @param BufferSize  On input the size of Buffer in bytes. On output with a return
+                     code of EFI_SUCCESS, the amount of data transferred to Buffer.
+                     On output with a return code of EFI_BUFFER_TOO_SMALL,
+                     the size of Buffer required to retrieve the requested file.
+  @param Buffer      The memory buffer to transfer the file to. If Buffer is NULL,
+                     then no the size of the requested file is returned in BufferSize.
+
+  @retval EFI_SUCCESS           The file was loaded.
+  @retval EFI_UNSUPPORTED       BootPolicy is TRUE.
+  @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or
+                                BufferSize is NULL.
+  @retval EFI_NOT_FOUND         Not found PCI Option Rom on PCI device.
+  @retval EFI_DEVICE_ERROR      Failed to decompress PCI Option Rom image.
+  @retval EFI_BUFFER_TOO_SMALL  The BufferSize is too small to read the current directory entry.
+                                BufferSize has been updated with the size needed to complete the request.
+
+**/
+EFI_STATUS
+EFIAPI
+LoadFile2 (
+  IN EFI_LOAD_FILE2_PROTOCOL  *This,
+  IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+  IN BOOLEAN                  BootPolicy,
+  IN OUT UINTN                *BufferSize,
+  IN VOID                     *Buffer      OPTIONAL
+  );
+
+/**
+  Check if the RomImage contains EFI Images.
+
+  @param  RomImage  The ROM address of Image for check.
+  @param  RomSize   Size of ROM for check.
+
+  @retval TRUE     ROM contain EFI Image.
+  @retval FALSE    ROM not contain EFI Image.
+
+**/
+BOOLEAN
+ContainEfiImage (
+  IN VOID            *RomImage,
+  IN UINT64          RomSize
+  );
+
+/**
+  Get Pci device's oprom information.
+
+  @param PciIoDevice    Input Pci device instance.
+                        Output Pci device instance with updated OptionRom size.
+
+  @retval EFI_NOT_FOUND Pci device has not Option Rom.
+  @retval EFI_SUCCESS   Pci device has Option Rom.
+
+**/
+EFI_STATUS
+GetOpRomInfo (
+  IN OUT PCI_IO_DEVICE    *PciIoDevice
+  );
+
+/**
+  Load Option Rom image for specified PCI device.
+
+  @param PciDevice Pci device instance.
+  @param RomBase   Base address of Option Rom.
+
+  @retval EFI_OUT_OF_RESOURCES No enough memory to hold image.
+  @retval EFI_SUCESS           Successfully loaded Option Rom.
+
+**/
+EFI_STATUS
+LoadOpRomImage (
+  IN PCI_IO_DEVICE   *PciDevice,
+  IN UINT64          RomBase
+  );
+
+/**
+  Enable/Disable Option Rom decode.
+
+  @param PciDevice    Pci device instance.
+  @param RomBarIndex  The BAR index of the standard PCI Configuration header to use as the
+                      base address for resource range. The legal range for this field is 0..5.
+  @param RomBar       Base address of Option Rom.
+  @param Enable       Flag for enable/disable decode.
+
+**/
+VOID
+RomDecode (
+  IN PCI_IO_DEVICE   *PciDevice,
+  IN UINT8           RomBarIndex,
+  IN UINT32          RomBar,
+  IN BOOLEAN         Enable
+  );
+
+/**
+  Load and start the Option Rom image.
+
+  @param PciDevice       Pci device instance.
+
+  @retval EFI_SUCCESS    Successfully loaded and started PCI Option Rom image.
+  @retval EFI_NOT_FOUND  Failed to process PCI Option Rom image.
+
+**/
+EFI_STATUS
+ProcessOpRomImage (
+  IN PCI_IO_DEVICE   *PciDevice
+  );
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.c
new file mode 100644
index 0000000000..cf3f8164cd
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.c
@@ -0,0 +1,82 @@
+/** @file
+  Power management support functions implementation for PCI Bus module.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+
+/**
+  This function is intended to turn off PWE assertion and
+  put the device to D0 state if the device supports
+  PCI Power Management.
+
+  @param PciIoDevice      PCI device instance.
+
+  @retval EFI_UNSUPPORTED PCI Device does not support power management.
+  @retval EFI_SUCCESS     Turned off PWE successfully.
+
+**/
+EFI_STATUS
+ResetPowerManagementFeature (
+  IN PCI_IO_DEVICE *PciIoDevice
+  )
+{
+  EFI_STATUS  Status;
+  UINT8       PowerManagementRegBlock;
+  UINT16      PowerManagementCSR;
+
+  PowerManagementRegBlock = 0;
+
+  Status = LocateCapabilityRegBlock (
+            PciIoDevice,
+            EFI_PCI_CAPABILITY_ID_PMI,
+            &PowerManagementRegBlock,
+            NULL
+            );
+
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Turn off the PWE assertion and put the device into D0 State
+  //
+
+  //
+  // Read PMCSR
+  //
+  Status = PciIoDevice->PciIo.Pci.Read (
+                                    &PciIoDevice->PciIo,
+                                    EfiPciIoWidthUint16,
+                                    PowerManagementRegBlock + 4,
+                                    1,
+                                    &PowerManagementCSR
+                                    );
+
+  if (!EFI_ERROR (Status)) {
+    //
+    // Clear PME_Status bit
+    //
+    PowerManagementCSR |= BIT15;
+    //
+    // Clear PME_En bit. PowerState = D0.
+    //
+    PowerManagementCSR &= ~(BIT8 | BIT1 | BIT0);
+
+    //
+    // Write PMCSR
+    //
+    Status = PciIoDevice->PciIo.Pci.Write (
+                                      &PciIoDevice->PciIo,
+                                      EfiPciIoWidthUint16,
+                                      PowerManagementRegBlock + 4,
+                                      1,
+                                      &PowerManagementCSR
+                                      );
+  }
+  return Status;
+}
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.h
new file mode 100644
index 0000000000..44e97ec45a
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.h
@@ -0,0 +1,28 @@
+/** @file
+  Power management support functions declaration for PCI Bus module.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_PCI_POWER_MANAGEMENT_H_
+#define _EFI_PCI_POWER_MANAGEMENT_H_
+
+/**
+  This function is intended to turn off PWE assertion and
+  put the device to D0 state if the device supports
+  PCI Power Management.
+
+  @param PciIoDevice      PCI device instance.
+
+  @retval EFI_UNSUPPORTED PCI Device does not support power management.
+  @retval EFI_SUCCESS     Turned off PWE successfully.
+
+**/
+EFI_STATUS
+ResetPowerManagementFeature (
+  IN PCI_IO_DEVICE *PciIoDevice
+  );
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
new file mode 100644
index 0000000000..1461af7d5d
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
@@ -0,0 +1,2292 @@
+/** @file
+  PCI resources support functions implementation for PCI Bus module.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+
+//
+// The default policy for the PCI bus driver is NOT to reserve I/O ranges for both ISA aliases and VGA aliases.
+//
+BOOLEAN mReserveIsaAliases = FALSE;
+BOOLEAN mReserveVgaAliases = FALSE;
+BOOLEAN mPolicyDetermined  = FALSE;
+
+/**
+  The function is used to skip VGA range.
+
+  @param Start    Returned start address including VGA range.
+  @param Length   The length of VGA range.
+
+**/
+VOID
+SkipVGAAperture (
+  OUT UINT64   *Start,
+  IN  UINT64   Length
+  )
+{
+  UINT64  Original;
+  UINT64  Mask;
+  UINT64  StartOffset;
+  UINT64  LimitOffset;
+
+  ASSERT (Start != NULL);
+  //
+  // For legacy VGA, bit 10 to bit 15 is not decoded
+  //
+  Mask        = 0x3FF;
+
+  Original    = *Start;
+  StartOffset = Original & Mask;
+  LimitOffset = ((*Start) + Length - 1) & Mask;
+  if (LimitOffset >= VGABASE1) {
+    *Start = *Start - StartOffset + VGALIMIT2 + 1;
+  }
+}
+
+/**
+  This function is used to skip ISA aliasing aperture.
+
+  @param Start    Returned start address including ISA aliasing aperture.
+  @param Length   The length of ISA aliasing aperture.
+
+**/
+VOID
+SkipIsaAliasAperture (
+  OUT UINT64   *Start,
+  IN  UINT64   Length
+  )
+{
+
+  UINT64  Original;
+  UINT64  Mask;
+  UINT64  StartOffset;
+  UINT64  LimitOffset;
+
+  ASSERT (Start != NULL);
+
+  //
+  // For legacy ISA, bit 10 to bit 15 is not decoded
+  //
+  Mask        = 0x3FF;
+
+  Original    = *Start;
+  StartOffset = Original & Mask;
+  LimitOffset = ((*Start) + Length - 1) & Mask;
+
+  if (LimitOffset >= ISABASE) {
+    *Start = *Start - StartOffset + ISALIMIT + 1;
+  }
+}
+
+/**
+  This function inserts a resource node into the resource list.
+  The resource list is sorted in descend order.
+
+  @param Bridge  PCI resource node for bridge.
+  @param ResNode Resource node want to be inserted.
+
+**/
+VOID
+InsertResourceNode (
+  IN OUT PCI_RESOURCE_NODE   *Bridge,
+  IN     PCI_RESOURCE_NODE   *ResNode
+  )
+{
+  LIST_ENTRY        *CurrentLink;
+  PCI_RESOURCE_NODE *Temp;
+  UINT64            ResNodeAlignRest;
+  UINT64            TempAlignRest;
+
+  ASSERT (Bridge  != NULL);
+  ASSERT (ResNode != NULL);
+
+  InsertHeadList (&Bridge->ChildList, &ResNode->Link);
+
+  CurrentLink = Bridge->ChildList.ForwardLink->ForwardLink;
+  while (CurrentLink != &Bridge->ChildList) {
+    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+    if (ResNode->Alignment > Temp->Alignment) {
+      break;
+    } else if (ResNode->Alignment == Temp->Alignment) {
+      ResNodeAlignRest  = ResNode->Length & ResNode->Alignment;
+      TempAlignRest     = Temp->Length & Temp->Alignment;
+      if ((ResNodeAlignRest == 0) || (ResNodeAlignRest >= TempAlignRest)) {
+        break;
+      }
+    }
+
+    SwapListEntries (&ResNode->Link, CurrentLink);
+
+    CurrentLink = ResNode->Link.ForwardLink;
+  }
+}
+
+/**
+  This routine is used to merge two different resource trees in need of
+  resource degradation.
+
+  For example, if an upstream PPB doesn't support,
+  prefetchable memory decoding, the PCI bus driver will choose to call this function
+  to merge prefetchable memory resource list into normal memory list.
+
+  If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource
+  type.
+  If Dst is NULL or Res is NULL, ASSERT ().
+
+  @param Dst        Point to destination resource tree.
+  @param Res        Point to source resource tree.
+  @param TypeMerge  If the TypeMerge is TRUE, Res resource type is changed to the type of
+                    destination resource type.
+
+**/
+VOID
+MergeResourceTree (
+  IN PCI_RESOURCE_NODE   *Dst,
+  IN PCI_RESOURCE_NODE   *Res,
+  IN BOOLEAN             TypeMerge
+  )
+{
+
+  LIST_ENTRY        *CurrentLink;
+  PCI_RESOURCE_NODE *Temp;
+
+  ASSERT (Dst != NULL);
+  ASSERT (Res != NULL);
+
+  while (!IsListEmpty (&Res->ChildList)) {
+    CurrentLink = Res->ChildList.ForwardLink;
+
+    Temp        = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+    if (TypeMerge) {
+      Temp->ResType = Dst->ResType;
+    }
+
+    RemoveEntryList (CurrentLink);
+    InsertResourceNode (Dst, Temp);
+  }
+}
+
+/**
+  This function is used to calculate the IO16 aperture
+  for a bridge.
+
+  @param Bridge    PCI resource node for bridge.
+
+**/
+VOID
+CalculateApertureIo16 (
+  IN PCI_RESOURCE_NODE    *Bridge
+  )
+{
+  EFI_STATUS              Status;
+  UINT64                  Aperture;
+  LIST_ENTRY              *CurrentLink;
+  PCI_RESOURCE_NODE       *Node;
+  UINT64                  Offset;
+  EFI_PCI_PLATFORM_POLICY PciPolicy;
+  UINT64                  PaddingAperture;
+
+  if (!mPolicyDetermined) {
+    //
+    // Check PciPlatform policy
+    //
+    Status = EFI_NOT_FOUND;
+    PciPolicy = 0;
+    if (gPciPlatformProtocol != NULL) {
+      Status = gPciPlatformProtocol->GetPlatformPolicy (
+                                       gPciPlatformProtocol,
+                                       &PciPolicy
+                                       );
+    }
+
+    if (EFI_ERROR (Status) && gPciOverrideProtocol != NULL) {
+      Status = gPciOverrideProtocol->GetPlatformPolicy (
+                                       gPciOverrideProtocol,
+                                       &PciPolicy
+                                       );
+    }
+
+    if (!EFI_ERROR (Status)) {
+      if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {
+        mReserveIsaAliases = TRUE;
+      }
+      if ((PciPolicy & EFI_RESERVE_VGA_IO_ALIAS) != 0) {
+        mReserveVgaAliases = TRUE;
+      }
+    }
+    mPolicyDetermined = TRUE;
+  }
+
+  Aperture        = 0;
+  PaddingAperture = 0;
+
+  if (Bridge == NULL) {
+    return ;
+  }
+
+  //
+  // Assume the bridge is aligned
+  //
+  for ( CurrentLink = GetFirstNode (&Bridge->ChildList)
+      ; !IsNull (&Bridge->ChildList, CurrentLink)
+      ; CurrentLink = GetNextNode (&Bridge->ChildList, CurrentLink)
+      ) {
+
+    Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
+    if (Node->ResourceUsage == PciResUsagePadding) {
+      ASSERT (PaddingAperture == 0);
+      PaddingAperture = Node->Length;
+      continue;
+    }
+    //
+    // Consider the aperture alignment
+    //
+    Offset = Aperture & (Node->Alignment);
+
+    if (Offset != 0) {
+
+      Aperture = Aperture + (Node->Alignment + 1) - Offset;
+
+    }
+
+    //
+    // IsaEnable and VGAEnable can not be implemented now.
+    // If both of them are enabled, then the IO resource would
+    // become too limited to meet the requirement of most of devices.
+    //
+    if (mReserveIsaAliases || mReserveVgaAliases) {
+      if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci)) && !IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
+        //
+        // Check if there is need to support ISA/VGA decoding
+        // If so, we need to avoid isa/vga aliasing range
+        //
+        if (mReserveIsaAliases) {
+          SkipIsaAliasAperture (
+            &Aperture,
+            Node->Length
+            );
+          Offset = Aperture & (Node->Alignment);
+          if (Offset != 0) {
+            Aperture = Aperture + (Node->Alignment + 1) - Offset;
+          }
+        } else if (mReserveVgaAliases) {
+          SkipVGAAperture (
+            &Aperture,
+            Node->Length
+            );
+          Offset = Aperture & (Node->Alignment);
+          if (Offset != 0) {
+            Aperture = Aperture + (Node->Alignment + 1) - Offset;
+          }
+        }
+      }
+    }
+
+    Node->Offset = Aperture;
+
+    //
+    // Increment aperture by the length of node
+    //
+    Aperture += Node->Length;
+  }
+
+  //
+  // Adjust the aperture with the bridge's alignment
+  //
+  Offset = Aperture & (Bridge->Alignment);
+
+  if (Offset != 0) {
+    Aperture = Aperture + (Bridge->Alignment + 1) - Offset;
+  }
+
+  Bridge->Length = Aperture;
+  //
+  // At last, adjust the bridge's alignment to the first child's alignment
+  // if the bridge has at least one child
+  //
+  CurrentLink = Bridge->ChildList.ForwardLink;
+  if (CurrentLink != &Bridge->ChildList) {
+    Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
+    if (Node->Alignment > Bridge->Alignment) {
+      Bridge->Alignment = Node->Alignment;
+    }
+  }
+
+  //
+  // Hotplug controller needs padding resources.
+  // Use the larger one between the padding resource and actual occupied resource.
+  //
+  Bridge->Length = MAX (Bridge->Length, PaddingAperture);
+}
+
+/**
+  This function is used to calculate the resource aperture
+  for a given bridge device.
+
+  @param Bridge      PCI resource node for given bridge device.
+
+**/
+VOID
+CalculateResourceAperture (
+  IN PCI_RESOURCE_NODE    *Bridge
+  )
+{
+  UINT64            Aperture[2];
+  LIST_ENTRY        *CurrentLink;
+  PCI_RESOURCE_NODE *Node;
+
+  if (Bridge == NULL) {
+    return ;
+  }
+
+  if (Bridge->ResType == PciBarTypeIo16) {
+
+    CalculateApertureIo16 (Bridge);
+    return ;
+  }
+
+  Aperture[PciResUsageTypical] = 0;
+  Aperture[PciResUsagePadding] = 0;
+  //
+  // Assume the bridge is aligned
+  //
+  for ( CurrentLink = GetFirstNode (&Bridge->ChildList)
+      ; !IsNull (&Bridge->ChildList, CurrentLink)
+      ; CurrentLink = GetNextNode (&Bridge->ChildList, CurrentLink)
+      ) {
+    Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+    //
+    // It's possible for a bridge to contain multiple padding resource
+    // nodes due to DegradeResource().
+    //
+    ASSERT ((Node->ResourceUsage == PciResUsageTypical) ||
+            (Node->ResourceUsage == PciResUsagePadding));
+    ASSERT (Node->ResourceUsage < ARRAY_SIZE (Aperture));
+    //
+    // Recode current aperture as a offset
+    // Apply padding resource to meet alignment requirement
+    // Node offset will be used in future real allocation
+    //
+    Node->Offset = ALIGN_VALUE (Aperture[Node->ResourceUsage], Node->Alignment + 1);
+
+    //
+    // Record the total aperture.
+    //
+    Aperture[Node->ResourceUsage] = Node->Offset + Node->Length;
+  }
+
+  //
+  // Adjust the aperture with the bridge's alignment
+  //
+  Aperture[PciResUsageTypical] = ALIGN_VALUE (Aperture[PciResUsageTypical], Bridge->Alignment + 1);
+  Aperture[PciResUsagePadding] = ALIGN_VALUE (Aperture[PciResUsagePadding], Bridge->Alignment + 1);
+
+  //
+  // Hotplug controller needs padding resources.
+  // Use the larger one between the padding resource and actual occupied resource.
+  //
+  Bridge->Length = MAX (Aperture[PciResUsageTypical], Aperture[PciResUsagePadding]);
+
+  //
+  // Adjust the bridge's alignment to the MAX (first) alignment of all children.
+  //
+  CurrentLink = Bridge->ChildList.ForwardLink;
+  if (CurrentLink != &Bridge->ChildList) {
+    Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
+    if (Node->Alignment > Bridge->Alignment) {
+      Bridge->Alignment = Node->Alignment;
+    }
+  }
+}
+
+/**
+  Get IO/Memory resource info for given PCI device.
+
+  @param PciDev     Pci device instance.
+  @param IoNode     Resource info node for IO .
+  @param Mem32Node  Resource info node for 32-bit memory.
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
+  @param Mem64Node  Resource info node for 64-bit memory.
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
+
+**/
+VOID
+GetResourceFromDevice (
+  IN     PCI_IO_DEVICE     *PciDev,
+  IN OUT PCI_RESOURCE_NODE *IoNode,
+  IN OUT PCI_RESOURCE_NODE *Mem32Node,
+  IN OUT PCI_RESOURCE_NODE *PMem32Node,
+  IN OUT PCI_RESOURCE_NODE *Mem64Node,
+  IN OUT PCI_RESOURCE_NODE *PMem64Node
+  )
+{
+
+  UINT8             Index;
+  PCI_RESOURCE_NODE *Node;
+  BOOLEAN           ResourceRequested;
+
+  Node              = NULL;
+  ResourceRequested = FALSE;
+
+  for (Index = 0; Index < PCI_MAX_BAR; Index++) {
+
+    switch ((PciDev->PciBar)[Index].BarType) {
+
+    case PciBarTypeMem32:
+    case PciBarTypeOpRom:
+
+      Node = CreateResourceNode (
+              PciDev,
+              (PciDev->PciBar)[Index].Length,
+              (PciDev->PciBar)[Index].Alignment,
+              Index,
+              (PciDev->PciBar)[Index].BarType,
+              PciResUsageTypical
+              );
+
+      InsertResourceNode (
+        Mem32Node,
+        Node
+        );
+
+      ResourceRequested = TRUE;
+      break;
+
+    case PciBarTypeMem64:
+
+      Node = CreateResourceNode (
+              PciDev,
+              (PciDev->PciBar)[Index].Length,
+              (PciDev->PciBar)[Index].Alignment,
+              Index,
+              PciBarTypeMem64,
+              PciResUsageTypical
+              );
+
+      InsertResourceNode (
+        Mem64Node,
+        Node
+        );
+
+      ResourceRequested = TRUE;
+      break;
+
+    case PciBarTypePMem64:
+
+      Node = CreateResourceNode (
+              PciDev,
+              (PciDev->PciBar)[Index].Length,
+              (PciDev->PciBar)[Index].Alignment,
+              Index,
+              PciBarTypePMem64,
+              PciResUsageTypical
+              );
+
+      InsertResourceNode (
+        PMem64Node,
+        Node
+        );
+
+      ResourceRequested = TRUE;
+      break;
+
+    case PciBarTypePMem32:
+
+      Node = CreateResourceNode (
+              PciDev,
+              (PciDev->PciBar)[Index].Length,
+              (PciDev->PciBar)[Index].Alignment,
+              Index,
+              PciBarTypePMem32,
+              PciResUsageTypical
+              );
+
+      InsertResourceNode (
+        PMem32Node,
+        Node
+        );
+      ResourceRequested = TRUE;
+      break;
+
+    case PciBarTypeIo16:
+    case PciBarTypeIo32:
+
+      Node = CreateResourceNode (
+              PciDev,
+              (PciDev->PciBar)[Index].Length,
+              (PciDev->PciBar)[Index].Alignment,
+              Index,
+              PciBarTypeIo16,
+              PciResUsageTypical
+              );
+
+      InsertResourceNode (
+        IoNode,
+        Node
+        );
+      ResourceRequested = TRUE;
+      break;
+
+    case PciBarTypeUnknown:
+      break;
+
+    default:
+      break;
+    }
+  }
+
+  //
+  // Add VF resource
+  //
+  for (Index = 0; Index < PCI_MAX_BAR; Index++) {
+
+    switch ((PciDev->VfPciBar)[Index].BarType) {
+
+    case PciBarTypeMem32:
+
+      Node = CreateVfResourceNode (
+              PciDev,
+              (PciDev->VfPciBar)[Index].Length,
+              (PciDev->VfPciBar)[Index].Alignment,
+              Index,
+              PciBarTypeMem32,
+              PciResUsageTypical
+              );
+
+      InsertResourceNode (
+        Mem32Node,
+        Node
+        );
+
+      break;
+
+    case PciBarTypeMem64:
+
+      Node = CreateVfResourceNode (
+              PciDev,
+              (PciDev->VfPciBar)[Index].Length,
+              (PciDev->VfPciBar)[Index].Alignment,
+              Index,
+              PciBarTypeMem64,
+              PciResUsageTypical
+              );
+
+      InsertResourceNode (
+        Mem64Node,
+        Node
+        );
+
+      break;
+
+    case PciBarTypePMem64:
+
+      Node = CreateVfResourceNode (
+              PciDev,
+              (PciDev->VfPciBar)[Index].Length,
+              (PciDev->VfPciBar)[Index].Alignment,
+              Index,
+              PciBarTypePMem64,
+              PciResUsageTypical
+              );
+
+      InsertResourceNode (
+        PMem64Node,
+        Node
+        );
+
+      break;
+
+    case PciBarTypePMem32:
+
+      Node = CreateVfResourceNode (
+              PciDev,
+              (PciDev->VfPciBar)[Index].Length,
+              (PciDev->VfPciBar)[Index].Alignment,
+              Index,
+              PciBarTypePMem32,
+              PciResUsageTypical
+              );
+
+      InsertResourceNode (
+        PMem32Node,
+        Node
+        );
+      break;
+
+    case PciBarTypeIo16:
+    case PciBarTypeIo32:
+      break;
+
+    case PciBarTypeUnknown:
+      break;
+
+    default:
+      break;
+    }
+  }
+  // If there is no resource requested from this device,
+  // then we indicate this device has been allocated naturally.
+  //
+  if (!ResourceRequested) {
+    PciDev->Allocated = TRUE;
+  }
+}
+
+/**
+  This function is used to create a resource node.
+
+  @param PciDev       Pci device instance.
+  @param Length       Length of Io/Memory resource.
+  @param Alignment    Alignment of resource.
+  @param Bar          Bar index.
+  @param ResType      Type of resource: IO/Memory.
+  @param ResUsage     Resource usage.
+
+  @return PCI resource node created for given PCI device.
+          NULL means PCI resource node is not created.
+
+**/
+PCI_RESOURCE_NODE *
+CreateResourceNode (
+  IN PCI_IO_DEVICE         *PciDev,
+  IN UINT64                Length,
+  IN UINT64                Alignment,
+  IN UINT8                 Bar,
+  IN PCI_BAR_TYPE          ResType,
+  IN PCI_RESOURCE_USAGE    ResUsage
+  )
+{
+  PCI_RESOURCE_NODE *Node;
+
+  Node    = NULL;
+
+  Node    = AllocateZeroPool (sizeof (PCI_RESOURCE_NODE));
+  ASSERT (Node != NULL);
+  if (Node == NULL) {
+    return NULL;
+  }
+
+  Node->Signature     = PCI_RESOURCE_SIGNATURE;
+  Node->PciDev        = PciDev;
+  Node->Length        = Length;
+  Node->Alignment     = Alignment;
+  Node->Bar           = Bar;
+  Node->ResType       = ResType;
+  Node->Reserved      = FALSE;
+  Node->ResourceUsage = ResUsage;
+  InitializeListHead (&Node->ChildList);
+
+  return Node;
+}
+
+/**
+  This function is used to create a IOV VF resource node.
+
+  @param PciDev       Pci device instance.
+  @param Length       Length of Io/Memory resource.
+  @param Alignment    Alignment of resource.
+  @param Bar          Bar index.
+  @param ResType      Type of resource: IO/Memory.
+  @param ResUsage     Resource usage.
+
+  @return PCI resource node created for given VF PCI device.
+          NULL means PCI resource node is not created.
+
+**/
+PCI_RESOURCE_NODE *
+CreateVfResourceNode (
+  IN PCI_IO_DEVICE         *PciDev,
+  IN UINT64                Length,
+  IN UINT64                Alignment,
+  IN UINT8                 Bar,
+  IN PCI_BAR_TYPE          ResType,
+  IN PCI_RESOURCE_USAGE    ResUsage
+  )
+{
+  PCI_RESOURCE_NODE *Node;
+
+  Node = CreateResourceNode (PciDev, Length, Alignment, Bar, ResType, ResUsage);
+  if (Node == NULL) {
+    return Node;
+  }
+
+  Node->Virtual = TRUE;
+
+  return Node;
+}
+
+/**
+  This function is used to extract resource request from
+  device node list.
+
+  @param Bridge     Pci device instance.
+  @param IoNode     Resource info node for IO.
+  @param Mem32Node  Resource info node for 32-bit memory.
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
+  @param Mem64Node  Resource info node for 64-bit memory.
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
+
+**/
+VOID
+CreateResourceMap (
+  IN     PCI_IO_DEVICE     *Bridge,
+  IN OUT PCI_RESOURCE_NODE *IoNode,
+  IN OUT PCI_RESOURCE_NODE *Mem32Node,
+  IN OUT PCI_RESOURCE_NODE *PMem32Node,
+  IN OUT PCI_RESOURCE_NODE *Mem64Node,
+  IN OUT PCI_RESOURCE_NODE *PMem64Node
+  )
+{
+  PCI_IO_DEVICE     *Temp;
+  PCI_RESOURCE_NODE *IoBridge;
+  PCI_RESOURCE_NODE *Mem32Bridge;
+  PCI_RESOURCE_NODE *PMem32Bridge;
+  PCI_RESOURCE_NODE *Mem64Bridge;
+  PCI_RESOURCE_NODE *PMem64Bridge;
+  LIST_ENTRY        *CurrentLink;
+
+  CurrentLink = Bridge->ChildList.ForwardLink;
+
+  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
+
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    //
+    // Create resource nodes for this device by scanning the
+    // Bar array in the device private data
+    // If the upstream bridge doesn't support this device,
+    // no any resource node will be created for this device
+    //
+    GetResourceFromDevice (
+      Temp,
+      IoNode,
+      Mem32Node,
+      PMem32Node,
+      Mem64Node,
+      PMem64Node
+      );
+
+    if (IS_PCI_BRIDGE (&Temp->Pci)) {
+
+      //
+      // If the device has children, create a bridge resource node for this PPB
+      // Note: For PPB, memory aperture is aligned with 1MB and IO aperture
+      // is aligned with 4KB (smaller alignments may be supported).
+      //
+      IoBridge = CreateResourceNode (
+                   Temp,
+                   0,
+                   Temp->BridgeIoAlignment,
+                   PPB_IO_RANGE,
+                   PciBarTypeIo16,
+                   PciResUsageTypical
+                   );
+
+      Mem32Bridge = CreateResourceNode (
+                      Temp,
+                      0,
+                      0xFFFFF,
+                      PPB_MEM32_RANGE,
+                      PciBarTypeMem32,
+                      PciResUsageTypical
+                      );
+
+      PMem32Bridge = CreateResourceNode (
+                       Temp,
+                       0,
+                       0xFFFFF,
+                       PPB_PMEM32_RANGE,
+                       PciBarTypePMem32,
+                       PciResUsageTypical
+                       );
+
+      Mem64Bridge = CreateResourceNode (
+                      Temp,
+                      0,
+                      0xFFFFF,
+                      PPB_MEM64_RANGE,
+                      PciBarTypeMem64,
+                      PciResUsageTypical
+                      );
+
+      PMem64Bridge = CreateResourceNode (
+                       Temp,
+                       0,
+                       0xFFFFF,
+                       PPB_PMEM64_RANGE,
+                       PciBarTypePMem64,
+                       PciResUsageTypical
+                       );
+
+      //
+      // Recursively create resource map on this bridge
+      //
+      CreateResourceMap (
+        Temp,
+        IoBridge,
+        Mem32Bridge,
+        PMem32Bridge,
+        Mem64Bridge,
+        PMem64Bridge
+        );
+
+      if (ResourceRequestExisted (IoBridge)) {
+        InsertResourceNode (
+          IoNode,
+          IoBridge
+          );
+      } else {
+        FreePool (IoBridge);
+        IoBridge = NULL;
+      }
+
+      //
+      // If there is node under this resource bridge,
+      // then calculate bridge's aperture of this type
+      // and insert it into the respective resource tree.
+      // If no, delete this resource bridge
+      //
+      if (ResourceRequestExisted (Mem32Bridge)) {
+        InsertResourceNode (
+          Mem32Node,
+          Mem32Bridge
+          );
+      } else {
+        FreePool (Mem32Bridge);
+        Mem32Bridge = NULL;
+      }
+
+      //
+      // If there is node under this resource bridge,
+      // then calculate bridge's aperture of this type
+      // and insert it into the respective resource tree.
+      // If no, delete this resource bridge
+      //
+      if (ResourceRequestExisted (PMem32Bridge)) {
+        InsertResourceNode (
+          PMem32Node,
+          PMem32Bridge
+          );
+      } else {
+        FreePool (PMem32Bridge);
+        PMem32Bridge = NULL;
+      }
+
+      //
+      // If there is node under this resource bridge,
+      // then calculate bridge's aperture of this type
+      // and insert it into the respective resource tree.
+      // If no, delete this resource bridge
+      //
+      if (ResourceRequestExisted (Mem64Bridge)) {
+        InsertResourceNode (
+          Mem64Node,
+          Mem64Bridge
+          );
+      } else {
+        FreePool (Mem64Bridge);
+        Mem64Bridge = NULL;
+      }
+
+      //
+      // If there is node under this resource bridge,
+      // then calculate bridge's aperture of this type
+      // and insert it into the respective resource tree.
+      // If no, delete this resource bridge
+      //
+      if (ResourceRequestExisted (PMem64Bridge)) {
+        InsertResourceNode (
+          PMem64Node,
+          PMem64Bridge
+          );
+      } else {
+        FreePool (PMem64Bridge);
+        PMem64Bridge = NULL;
+      }
+
+    }
+
+    //
+    // If it is P2C, apply hard coded resource padding
+    //
+    if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
+      ResourcePaddingForCardBusBridge (
+        Temp,
+        IoNode,
+        Mem32Node,
+        PMem32Node,
+        Mem64Node,
+        PMem64Node
+        );
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  //
+  // To do some platform specific resource padding ...
+  //
+  ResourcePaddingPolicy (
+    Bridge,
+    IoNode,
+    Mem32Node,
+    PMem32Node,
+    Mem64Node,
+    PMem64Node
+    );
+
+  //
+  // Degrade resource if necessary
+  //
+  DegradeResource (
+    Bridge,
+    Mem32Node,
+    PMem32Node,
+    Mem64Node,
+    PMem64Node
+    );
+
+  //
+  // Calculate resource aperture for this bridge device
+  //
+  CalculateResourceAperture (Mem32Node);
+  CalculateResourceAperture (PMem32Node);
+  CalculateResourceAperture (Mem64Node);
+  CalculateResourceAperture (PMem64Node);
+  CalculateResourceAperture (IoNode);
+}
+
+/**
+  This function is used to do the resource padding for a specific platform.
+
+  @param PciDev     Pci device instance.
+  @param IoNode     Resource info node for IO.
+  @param Mem32Node  Resource info node for 32-bit memory.
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
+  @param Mem64Node  Resource info node for 64-bit memory.
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
+
+**/
+VOID
+ResourcePaddingPolicy (
+  IN PCI_IO_DEVICE     *PciDev,
+  IN PCI_RESOURCE_NODE *IoNode,
+  IN PCI_RESOURCE_NODE *Mem32Node,
+  IN PCI_RESOURCE_NODE *PMem32Node,
+  IN PCI_RESOURCE_NODE *Mem64Node,
+  IN PCI_RESOURCE_NODE *PMem64Node
+  )
+{
+  //
+  // Create padding resource node
+  //
+  if (PciDev->ResourcePaddingDescriptors != NULL) {
+    ApplyResourcePadding (
+      PciDev,
+      IoNode,
+      Mem32Node,
+      PMem32Node,
+      Mem64Node,
+      PMem64Node
+      );
+  }
+}
+
+/**
+  This function is used to degrade resource if the upstream bridge
+  doesn't support certain resource. Degradation path is
+  PMEM64 -> MEM64  -> MEM32
+  PMEM64 -> PMEM32 -> MEM32
+  IO32   -> IO16.
+
+  @param Bridge     Pci device instance.
+  @param Mem32Node  Resource info node for 32-bit memory.
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
+  @param Mem64Node  Resource info node for 64-bit memory.
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
+
+**/
+VOID
+DegradeResource (
+  IN PCI_IO_DEVICE     *Bridge,
+  IN PCI_RESOURCE_NODE *Mem32Node,
+  IN PCI_RESOURCE_NODE *PMem32Node,
+  IN PCI_RESOURCE_NODE *Mem64Node,
+  IN PCI_RESOURCE_NODE *PMem64Node
+  )
+{
+  PCI_IO_DEVICE        *PciIoDevice;
+  LIST_ENTRY           *ChildDeviceLink;
+  LIST_ENTRY           *ChildNodeLink;
+  LIST_ENTRY           *NextChildNodeLink;
+  PCI_RESOURCE_NODE    *ResourceNode;
+
+  if (FeaturePcdGet (PcdPciDegradeResourceForOptionRom)) {
+    //
+    // If any child device has both option ROM and 64-bit BAR, degrade its PMEM64/MEM64
+    // requests in case that if a legacy option ROM image can not access 64-bit resources.
+    //
+    ChildDeviceLink = Bridge->ChildList.ForwardLink;
+    while (ChildDeviceLink != NULL && ChildDeviceLink != &Bridge->ChildList) {
+      PciIoDevice = PCI_IO_DEVICE_FROM_LINK (ChildDeviceLink);
+      if (PciIoDevice->RomSize != 0) {
+        if (!IsListEmpty (&Mem64Node->ChildList)) {
+          ChildNodeLink = Mem64Node->ChildList.ForwardLink;
+          while (ChildNodeLink != &Mem64Node->ChildList) {
+            ResourceNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);
+            NextChildNodeLink = ChildNodeLink->ForwardLink;
+
+            if ((ResourceNode->PciDev == PciIoDevice) &&
+                (ResourceNode->Virtual || !PciIoDevice->PciBar[ResourceNode->Bar].BarTypeFixed)
+                ) {
+              RemoveEntryList (ChildNodeLink);
+              InsertResourceNode (Mem32Node, ResourceNode);
+            }
+            ChildNodeLink = NextChildNodeLink;
+          }
+        }
+
+        if (!IsListEmpty (&PMem64Node->ChildList)) {
+          ChildNodeLink = PMem64Node->ChildList.ForwardLink;
+          while (ChildNodeLink != &PMem64Node->ChildList) {
+            ResourceNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);
+            NextChildNodeLink = ChildNodeLink->ForwardLink;
+
+            if ((ResourceNode->PciDev == PciIoDevice) &&
+                (ResourceNode->Virtual || !PciIoDevice->PciBar[ResourceNode->Bar].BarTypeFixed)
+                ) {
+              RemoveEntryList (ChildNodeLink);
+              InsertResourceNode (PMem32Node, ResourceNode);
+            }
+            ChildNodeLink = NextChildNodeLink;
+          }
+        }
+
+      }
+      ChildDeviceLink = ChildDeviceLink->ForwardLink;
+    }
+  }
+
+  //
+  // If firmware is in 32-bit mode,
+  // then degrade PMEM64/MEM64 requests
+  //
+  if (sizeof (UINTN) <= 4) {
+    MergeResourceTree (
+      Mem32Node,
+      Mem64Node,
+      TRUE
+      );
+
+    MergeResourceTree (
+      PMem32Node,
+      PMem64Node,
+      TRUE
+      );
+  } else {
+    //
+    // if the bridge does not support MEM64, degrade MEM64 to MEM32
+    //
+    if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {
+        MergeResourceTree (
+          Mem32Node,
+          Mem64Node,
+          TRUE
+          );
+    }
+
+    //
+    // if the bridge does not support PMEM64, degrade PMEM64 to PMEM32
+    //
+    if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {
+      MergeResourceTree (
+        PMem32Node,
+        PMem64Node,
+        TRUE
+        );
+    }
+
+    //
+    // if both PMEM64 and PMEM32 requests from child devices, which can not be satisfied
+    // by a P2P bridge simultaneously, keep PMEM64 and degrade PMEM32 to MEM32.
+    //
+    if (!IsListEmpty (&PMem64Node->ChildList) && Bridge->Parent != NULL) {
+      MergeResourceTree (
+        Mem32Node,
+        PMem32Node,
+        TRUE
+        );
+    }
+  }
+
+  //
+  // If bridge doesn't support Pmem32
+  // degrade it to mem32
+  //
+  if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {
+    MergeResourceTree (
+      Mem32Node,
+      PMem32Node,
+      TRUE
+      );
+  }
+
+  //
+  // if root bridge supports combined Pmem Mem decoding
+  // merge these two type of resource
+  //
+  if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {
+    MergeResourceTree (
+      Mem32Node,
+      PMem32Node,
+      FALSE
+      );
+
+    //
+    // No need to check if to degrade MEM64 after merge, because
+    // if there are PMEM64 still here, 64-bit decode should be supported
+    // by the root bride.
+    //
+    MergeResourceTree (
+      Mem64Node,
+      PMem64Node,
+      FALSE
+      );
+  }
+}
+
+/**
+  Test whether bridge device support decode resource.
+
+  @param Bridge    Bridge device instance.
+  @param Decode    Decode type according to resource type.
+
+  @return TRUE     The bridge device support decode resource.
+  @return FALSE    The bridge device don't support decode resource.
+
+**/
+BOOLEAN
+BridgeSupportResourceDecode (
+  IN PCI_IO_DEVICE *Bridge,
+  IN UINT32        Decode
+  )
+{
+  if (((Bridge->Decodes) & Decode) != 0) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  This function is used to program the resource allocated
+  for each resource node under specified bridge.
+
+  @param Base     Base address of resource to be programmed.
+  @param Bridge   PCI resource node for the bridge device.
+
+  @retval EFI_SUCCESS            Successfully to program all resources
+                                 on given PCI bridge device.
+  @retval EFI_OUT_OF_RESOURCES   Base is all one.
+
+**/
+EFI_STATUS
+ProgramResource (
+  IN UINT64            Base,
+  IN PCI_RESOURCE_NODE *Bridge
+  )
+{
+  LIST_ENTRY        *CurrentLink;
+  PCI_RESOURCE_NODE *Node;
+  EFI_STATUS        Status;
+
+  if (Base == gAllOne) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  CurrentLink = Bridge->ChildList.ForwardLink;
+
+  while (CurrentLink != &Bridge->ChildList) {
+
+    Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+    if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {
+
+      if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
+        //
+        // Program the PCI Card Bus device
+        //
+        ProgramP2C (Base, Node);
+      } else {
+        //
+        // Program the PCI device BAR
+        //
+        ProgramBar (Base, Node);
+      }
+    } else {
+      //
+      // Program the PCI devices under this bridge
+      //
+      Status = ProgramResource (Base + Node->Offset, Node);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      ProgramPpbApperture (Base, Node);
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Program Bar register for PCI device.
+
+  @param Base  Base address for PCI device resource to be programmed.
+  @param Node  Point to resource node structure.
+
+**/
+VOID
+ProgramBar (
+  IN UINT64            Base,
+  IN PCI_RESOURCE_NODE *Node
+  )
+{
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  UINT64              Address;
+  UINT32              Address32;
+
+  ASSERT (Node->Bar < PCI_MAX_BAR);
+
+  //
+  // Check VF BAR
+  //
+  if (Node->Virtual) {
+    ProgramVfBar (Base, Node);
+    return;
+  }
+
+  Address = 0;
+  PciIo   = &(Node->PciDev->PciIo);
+
+  Address = Base + Node->Offset;
+
+  //
+  // Indicate pci bus driver has allocated
+  // resource for this device
+  // It might be a temporary solution here since
+  // pci device could have multiple bar
+  //
+  Node->PciDev->Allocated = TRUE;
+
+  switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
+
+  case PciBarTypeIo16:
+  case PciBarTypeIo32:
+  case PciBarTypeMem32:
+  case PciBarTypePMem32:
+
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint32,
+                 (Node->PciDev->PciBar[Node->Bar]).Offset,
+                 1,
+                 &Address
+                 );
+  //
+  // Continue to the case PciBarTypeOpRom to set the BaseAddress.
+  // PciBarTypeOpRom is a virtual BAR only in root bridge, to capture
+  // the MEM32 resource requirement for Option ROM shadow.
+  //
+
+  case PciBarTypeOpRom:
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+
+    break;
+
+  case PciBarTypeMem64:
+  case PciBarTypePMem64:
+
+    Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
+
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint32,
+                 (Node->PciDev->PciBar[Node->Bar]).Offset,
+                 1,
+                 &Address32
+                 );
+
+    Address32 = (UINT32) RShiftU64 (Address, 32);
+
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint32,
+                 (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
+                 1,
+                 &Address32
+                 );
+
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+
+    break;
+
+  default:
+    break;
+  }
+}
+
+/**
+  Program IOV VF Bar register for PCI device.
+
+  @param Base  Base address for PCI device resource to be programmed.
+  @param Node  Point to resource node structure.
+
+**/
+EFI_STATUS
+ProgramVfBar (
+  IN UINT64            Base,
+  IN PCI_RESOURCE_NODE *Node
+  )
+{
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  UINT64              Address;
+  UINT32              Address32;
+
+  ASSERT (Node->Bar < PCI_MAX_BAR);
+  ASSERT (Node->Virtual);
+
+  Address = 0;
+  PciIo   = &(Node->PciDev->PciIo);
+
+  Address = Base + Node->Offset;
+
+  //
+  // Indicate pci bus driver has allocated
+  // resource for this device
+  // It might be a temporary solution here since
+  // pci device could have multiple bar
+  //
+  Node->PciDev->Allocated = TRUE;
+
+  switch ((Node->PciDev->VfPciBar[Node->Bar]).BarType) {
+
+  case PciBarTypeMem32:
+  case PciBarTypePMem32:
+
+    PciIo->Pci.Write (
+                PciIo,
+                EfiPciIoWidthUint32,
+                (Node->PciDev->VfPciBar[Node->Bar]).Offset,
+                1,
+                &Address
+                );
+
+    Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;
+    break;
+
+  case PciBarTypeMem64:
+  case PciBarTypePMem64:
+
+    Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
+
+    PciIo->Pci.Write (
+                PciIo,
+                EfiPciIoWidthUint32,
+                (Node->PciDev->VfPciBar[Node->Bar]).Offset,
+                1,
+                &Address32
+                );
+
+    Address32 = (UINT32) RShiftU64 (Address, 32);
+
+    PciIo->Pci.Write (
+                PciIo,
+                EfiPciIoWidthUint32,
+                ((Node->PciDev->VfPciBar[Node->Bar]).Offset + 4),
+                1,
+                &Address32
+                );
+
+    Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;
+    break;
+
+  case PciBarTypeIo16:
+  case PciBarTypeIo32:
+    break;
+
+  default:
+    break;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Program PCI-PCI bridge aperture.
+
+  @param Base  Base address for resource.
+  @param Node  Point to resource node structure.
+
+**/
+VOID
+ProgramPpbApperture (
+  IN UINT64            Base,
+  IN PCI_RESOURCE_NODE *Node
+  )
+{
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  UINT64              Address;
+  UINT32              Address32;
+
+  Address = 0;
+  //
+  // If no device resource of this PPB, return anyway
+  // Aperture is set default in the initialization code
+  //
+  if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {
+    //
+    // For padding resource node, just ignore when programming
+    //
+    return ;
+  }
+
+  PciIo   = &(Node->PciDev->PciIo);
+  Address = Base + Node->Offset;
+
+  //
+  // Indicate the PPB resource has been allocated
+  //
+  Node->PciDev->Allocated = TRUE;
+
+  switch (Node->Bar) {
+
+  case PPB_BAR_0:
+  case PPB_BAR_1:
+    switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
+
+      case PciBarTypeIo16:
+      case PciBarTypeIo32:
+      case PciBarTypeMem32:
+      case PciBarTypePMem32:
+
+        PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint32,
+                 (Node->PciDev->PciBar[Node->Bar]).Offset,
+                 1,
+                 &Address
+                 );
+
+        Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+        Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
+        break;
+
+      case PciBarTypeMem64:
+      case PciBarTypePMem64:
+
+        Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
+
+        PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint32,
+                 (Node->PciDev->PciBar[Node->Bar]).Offset,
+                 1,
+                 &Address32
+                 );
+
+        Address32 = (UINT32) RShiftU64 (Address, 32);
+
+        PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint32,
+                 (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
+                 1,
+                 &Address32
+                 );
+
+        Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+        Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
+        break;
+
+      default:
+        break;
+    }
+    break;
+
+  case PPB_IO_RANGE:
+
+    Address32 = ((UINT32) (Address)) >> 8;
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint8,
+                 0x1C,
+                 1,
+                 &Address32
+                 );
+
+    Address32 >>= 8;
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint16,
+                 0x30,
+                 1,
+                 &Address32
+                 );
+
+    Address32 = (UINT32) (Address + Node->Length - 1);
+    Address32 = ((UINT32) (Address32)) >> 8;
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint8,
+                 0x1D,
+                 1,
+                 &Address32
+                 );
+
+    Address32 >>= 8;
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint16,
+                 0x32,
+                 1,
+                 &Address32
+                 );
+
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
+    break;
+
+  case PPB_MEM32_RANGE:
+
+    Address32 = ((UINT32) (Address)) >> 16;
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint16,
+                 0x20,
+                 1,
+                 &Address32
+                 );
+
+    Address32 = (UINT32) (Address + Node->Length - 1);
+    Address32 = ((UINT32) (Address32)) >> 16;
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint16,
+                 0x22,
+                 1,
+                 &Address32
+                 );
+
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
+    break;
+
+  case PPB_PMEM32_RANGE:
+  case PPB_PMEM64_RANGE:
+
+    Address32 = ((UINT32) (Address)) >> 16;
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint16,
+                 0x24,
+                 1,
+                 &Address32
+                 );
+
+    Address32 = (UINT32) (Address + Node->Length - 1);
+    Address32 = ((UINT32) (Address32)) >> 16;
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint16,
+                 0x26,
+                 1,
+                 &Address32
+                 );
+
+    Address32 = (UINT32) RShiftU64 (Address, 32);
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint32,
+                 0x28,
+                 1,
+                 &Address32
+                 );
+
+    Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint32,
+                 0x2C,
+                 1,
+                 &Address32
+                 );
+
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
+    break;
+
+  default:
+    break;
+  }
+}
+
+/**
+  Program parent bridge for Option Rom.
+
+  @param PciDevice      Pci device instance.
+  @param OptionRomBase  Base address for Option Rom.
+  @param Enable         Enable or disable PCI memory.
+
+**/
+VOID
+ProgramUpstreamBridgeForRom (
+  IN PCI_IO_DEVICE   *PciDevice,
+  IN UINT32          OptionRomBase,
+  IN BOOLEAN         Enable
+  )
+{
+  PCI_IO_DEVICE       *Parent;
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  UINT16              Base;
+  UINT16              Limit;
+  //
+  // For root bridge, just return.
+  //
+  Parent = PciDevice->Parent;
+  while (Parent != NULL) {
+    if (!IS_PCI_BRIDGE (&Parent->Pci)) {
+      break;
+    }
+
+    PciIo = &Parent->PciIo;
+
+    //
+    // Program PPB to only open a single <= 16MB aperture
+    //
+    if (Enable) {
+      //
+      // Only cover MMIO for Option ROM.
+      //
+      Base  = (UINT16) (OptionRomBase >> 16);
+      Limit = (UINT16) ((OptionRomBase + PciDevice->RomSize - 1) >> 16);
+      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase),  1, &Base);
+      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), 1, &Limit);
+
+      PCI_ENABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
+    } else {
+      //
+      // Cover 32bit MMIO for devices below the bridge.
+      //
+      if (Parent->PciBar[PPB_MEM32_RANGE].Length == 0) {
+        //
+        // When devices under the bridge contains Option ROM and doesn't require 32bit MMIO.
+        //
+        Base  = (UINT16) gAllOne;
+        Limit = (UINT16) gAllZero;
+      } else {
+        Base  = (UINT16) ((UINT32) Parent->PciBar[PPB_MEM32_RANGE].BaseAddress >> 16);
+        Limit = (UINT16) ((UINT32) (Parent->PciBar[PPB_MEM32_RANGE].BaseAddress
+                                    + Parent->PciBar[PPB_MEM32_RANGE].Length - 1) >> 16);
+      }
+      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase),  1, &Base);
+      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), 1, &Limit);
+
+      PCI_DISABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
+    }
+
+    Parent = Parent->Parent;
+  }
+}
+
+/**
+  Test whether resource exists for a bridge.
+
+  @param Bridge  Point to resource node for a bridge.
+
+  @retval TRUE   There is resource on the given bridge.
+  @retval FALSE  There isn't resource on the given bridge.
+
+**/
+BOOLEAN
+ResourceRequestExisted (
+  IN PCI_RESOURCE_NODE    *Bridge
+  )
+{
+  if (Bridge != NULL) {
+    if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  Initialize resource pool structure.
+
+  @param ResourcePool Point to resource pool structure. This pool
+                      is reset to all zero when returned.
+  @param ResourceType Type of resource.
+
+**/
+VOID
+InitializeResourcePool (
+  IN OUT PCI_RESOURCE_NODE   *ResourcePool,
+  IN     PCI_BAR_TYPE        ResourceType
+  )
+{
+  ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));
+  ResourcePool->ResType   = ResourceType;
+  ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;
+  InitializeListHead (&ResourcePool->ChildList);
+}
+
+/**
+  Destroy given resource tree.
+
+  @param Bridge  PCI resource root node of resource tree.
+
+**/
+VOID
+DestroyResourceTree (
+  IN PCI_RESOURCE_NODE *Bridge
+  )
+{
+  PCI_RESOURCE_NODE *Temp;
+  LIST_ENTRY        *CurrentLink;
+
+  while (!IsListEmpty (&Bridge->ChildList)) {
+
+    CurrentLink = Bridge->ChildList.ForwardLink;
+
+    Temp        = RESOURCE_NODE_FROM_LINK (CurrentLink);
+    ASSERT (Temp);
+
+    RemoveEntryList (CurrentLink);
+
+    if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {
+      DestroyResourceTree (Temp);
+    }
+
+    FreePool (Temp);
+  }
+}
+
+/**
+  Insert resource padding for P2C.
+
+  @param PciDev     Pci device instance.
+  @param IoNode     Resource info node for IO.
+  @param Mem32Node  Resource info node for 32-bit memory.
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
+  @param Mem64Node  Resource info node for 64-bit memory.
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
+
+**/
+VOID
+ResourcePaddingForCardBusBridge (
+  IN PCI_IO_DEVICE        *PciDev,
+  IN PCI_RESOURCE_NODE    *IoNode,
+  IN PCI_RESOURCE_NODE    *Mem32Node,
+  IN PCI_RESOURCE_NODE    *PMem32Node,
+  IN PCI_RESOURCE_NODE    *Mem64Node,
+  IN PCI_RESOURCE_NODE    *PMem64Node
+  )
+{
+  PCI_RESOURCE_NODE *Node;
+
+  Node = NULL;
+
+  //
+  // Memory Base/Limit Register 0
+  // Bar 1 decodes memory range 0
+  //
+  Node = CreateResourceNode (
+           PciDev,
+           0x2000000,
+           0x1ffffff,
+           1,
+           PciBarTypeMem32,
+           PciResUsagePadding
+           );
+
+  InsertResourceNode (
+    Mem32Node,
+    Node
+    );
+
+  //
+  // Memory Base/Limit Register 1
+  // Bar 2 decodes memory range1
+  //
+  Node = CreateResourceNode (
+           PciDev,
+           0x2000000,
+           0x1ffffff,
+           2,
+           PciBarTypePMem32,
+           PciResUsagePadding
+           );
+
+  InsertResourceNode (
+    PMem32Node,
+    Node
+    );
+
+  //
+  // Io Base/Limit
+  // Bar 3 decodes io range 0
+  //
+  Node = CreateResourceNode (
+           PciDev,
+           0x100,
+           0xff,
+           3,
+           PciBarTypeIo16,
+           PciResUsagePadding
+           );
+
+  InsertResourceNode (
+    IoNode,
+    Node
+    );
+
+  //
+  // Io Base/Limit
+  // Bar 4 decodes io range 0
+  //
+  Node = CreateResourceNode (
+           PciDev,
+           0x100,
+           0xff,
+           4,
+           PciBarTypeIo16,
+           PciResUsagePadding
+           );
+
+  InsertResourceNode (
+    IoNode,
+    Node
+    );
+}
+
+/**
+  Program PCI Card device register for given resource node.
+
+  @param Base    Base address of PCI Card device to be programmed.
+  @param Node    Given resource node.
+
+**/
+VOID
+ProgramP2C (
+  IN UINT64            Base,
+  IN PCI_RESOURCE_NODE *Node
+  )
+{
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  UINT64              Address;
+  UINT64              TempAddress;
+  UINT16              BridgeControl;
+
+  Address = 0;
+  PciIo   = &(Node->PciDev->PciIo);
+
+  Address = Base + Node->Offset;
+
+  //
+  // Indicate pci bus driver has allocated
+  // resource for this device
+  // It might be a temporary solution here since
+  // pci device could have multiple bar
+  //
+  Node->PciDev->Allocated = TRUE;
+
+  switch (Node->Bar) {
+
+  case P2C_BAR_0:
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint32,
+                 (Node->PciDev->PciBar[Node->Bar]).Offset,
+                 1,
+                 &Address
+                 );
+
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
+    break;
+
+  case P2C_MEM_1:
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint32,
+                 PCI_CARD_MEMORY_BASE_0,
+                 1,
+                 &Address
+                 );
+
+    TempAddress = Address + Node->Length - 1;
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint32,
+                 PCI_CARD_MEMORY_LIMIT_0,
+                 1,
+                 &TempAddress
+                 );
+
+    if (Node->ResType == PciBarTypeMem32) {
+      //
+      // Set non-prefetchable bit
+      //
+      PciIo->Pci.Read (
+                   PciIo,
+                   EfiPciIoWidthUint16,
+                   PCI_CARD_BRIDGE_CONTROL,
+                   1,
+                   &BridgeControl
+                   );
+
+      BridgeControl &= (UINT16) ~PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;
+      PciIo->Pci.Write (
+                   PciIo,
+                   EfiPciIoWidthUint16,
+                   PCI_CARD_BRIDGE_CONTROL,
+                   1,
+                   &BridgeControl
+                   );
+
+    } else {
+      //
+      // Set prefetchable bit
+      //
+      PciIo->Pci.Read (
+                   PciIo,
+                   EfiPciIoWidthUint16,
+                   PCI_CARD_BRIDGE_CONTROL,
+                   1,
+                   &BridgeControl
+                   );
+
+      BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;
+      PciIo->Pci.Write (
+                   PciIo,
+                   EfiPciIoWidthUint16,
+                   PCI_CARD_BRIDGE_CONTROL,
+                   1,
+                   &BridgeControl
+                   );
+    }
+
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
+    Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;
+
+    break;
+
+  case P2C_MEM_2:
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint32,
+                 PCI_CARD_MEMORY_BASE_1,
+                 1,
+                 &Address
+                 );
+
+    TempAddress = Address + Node->Length - 1;
+
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint32,
+                 PCI_CARD_MEMORY_LIMIT_1,
+                 1,
+                 &TempAddress
+                 );
+
+    if (Node->ResType == PciBarTypeMem32) {
+
+      //
+      // Set non-prefetchable bit
+      //
+      PciIo->Pci.Read (
+                   PciIo,
+                   EfiPciIoWidthUint16,
+                   PCI_CARD_BRIDGE_CONTROL,
+                   1,
+                   &BridgeControl
+                   );
+
+      BridgeControl &= (UINT16) ~(PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE);
+      PciIo->Pci.Write (
+                   PciIo,
+                   EfiPciIoWidthUint16,
+                   PCI_CARD_BRIDGE_CONTROL,
+                   1,
+                   &BridgeControl
+                   );
+
+    } else {
+
+      //
+      // Set prefetchable bit
+      //
+      PciIo->Pci.Read (
+                   PciIo,
+                   EfiPciIoWidthUint16,
+                   PCI_CARD_BRIDGE_CONTROL,
+                   1,
+                   &BridgeControl
+                   );
+
+      BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE;
+      PciIo->Pci.Write (
+                   PciIo,
+                   EfiPciIoWidthUint16,
+                   PCI_CARD_BRIDGE_CONTROL,
+                   1,
+                   &BridgeControl
+                   );
+    }
+
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
+    Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;
+    break;
+
+  case P2C_IO_1:
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint32,
+                 PCI_CARD_IO_BASE_0_LOWER,
+                 1,
+                 &Address
+                 );
+
+    TempAddress = Address + Node->Length - 1;
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint32,
+                 PCI_CARD_IO_LIMIT_0_LOWER,
+                 1,
+                 &TempAddress
+                 );
+
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
+    Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;
+
+    break;
+
+  case P2C_IO_2:
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint32,
+                 PCI_CARD_IO_BASE_1_LOWER,
+                 1,
+                 &Address
+                 );
+
+    TempAddress = Address + Node->Length - 1;
+    PciIo->Pci.Write (
+                 PciIo,
+                 EfiPciIoWidthUint32,
+                 PCI_CARD_IO_LIMIT_1_LOWER,
+                 1,
+                 &TempAddress
+                 );
+
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
+    Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;
+    break;
+
+  default:
+    break;
+  }
+}
+
+/**
+  Create padding resource node.
+
+  @param PciDev     Pci device instance.
+  @param IoNode     Resource info node for IO.
+  @param Mem32Node  Resource info node for 32-bit memory.
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
+  @param Mem64Node  Resource info node for 64-bit memory.
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
+
+**/
+VOID
+ApplyResourcePadding (
+  IN PCI_IO_DEVICE         *PciDev,
+  IN PCI_RESOURCE_NODE     *IoNode,
+  IN PCI_RESOURCE_NODE     *Mem32Node,
+  IN PCI_RESOURCE_NODE     *PMem32Node,
+  IN PCI_RESOURCE_NODE     *Mem64Node,
+  IN PCI_RESOURCE_NODE     *PMem64Node
+  )
+{
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+  PCI_RESOURCE_NODE                 *Node;
+  UINT8                             DummyBarIndex;
+
+  DummyBarIndex = 0;
+  Ptr           = PciDev->ResourcePaddingDescriptors;
+
+  while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {
+
+    if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {
+      if (Ptr->AddrLen != 0) {
+
+        Node = CreateResourceNode (
+                PciDev,
+                Ptr->AddrLen,
+                Ptr->AddrRangeMax,
+                DummyBarIndex,
+                PciBarTypeIo16,
+                PciResUsagePadding
+                );
+        InsertResourceNode (
+          IoNode,
+          Node
+          );
+      }
+
+      Ptr++;
+      continue;
+    }
+
+    if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
+
+      if (Ptr->AddrSpaceGranularity == 32) {
+
+        //
+        // prefetchable
+        //
+        if (Ptr->SpecificFlag == 0x6) {
+          if (Ptr->AddrLen != 0) {
+            Node = CreateResourceNode (
+                    PciDev,
+                    Ptr->AddrLen,
+                    Ptr->AddrRangeMax,
+                    DummyBarIndex,
+                    PciBarTypePMem32,
+                    PciResUsagePadding
+                    );
+            InsertResourceNode (
+              PMem32Node,
+              Node
+              );
+          }
+
+          Ptr++;
+          continue;
+        }
+
+        //
+        // Non-prefetchable
+        //
+        if (Ptr->SpecificFlag == 0) {
+          if (Ptr->AddrLen != 0) {
+            Node = CreateResourceNode (
+                    PciDev,
+                    Ptr->AddrLen,
+                    Ptr->AddrRangeMax,
+                    DummyBarIndex,
+                    PciBarTypeMem32,
+                    PciResUsagePadding
+                    );
+            InsertResourceNode (
+              Mem32Node,
+              Node
+              );
+          }
+
+          Ptr++;
+          continue;
+        }
+      }
+
+      if (Ptr->AddrSpaceGranularity == 64) {
+
+        //
+        // prefetchable
+        //
+        if (Ptr->SpecificFlag == 0x6) {
+          if (Ptr->AddrLen != 0) {
+            Node = CreateResourceNode (
+                    PciDev,
+                    Ptr->AddrLen,
+                    Ptr->AddrRangeMax,
+                    DummyBarIndex,
+                    PciBarTypePMem64,
+                    PciResUsagePadding
+                    );
+            InsertResourceNode (
+              PMem64Node,
+              Node
+              );
+          }
+
+          Ptr++;
+          continue;
+        }
+
+        //
+        // Non-prefetchable
+        //
+        if (Ptr->SpecificFlag == 0) {
+          if (Ptr->AddrLen != 0) {
+            Node = CreateResourceNode (
+                    PciDev,
+                    Ptr->AddrLen,
+                    Ptr->AddrRangeMax,
+                    DummyBarIndex,
+                    PciBarTypeMem64,
+                    PciResUsagePadding
+                    );
+            InsertResourceNode (
+              Mem64Node,
+              Node
+              );
+          }
+
+          Ptr++;
+          continue;
+        }
+      }
+    }
+
+    Ptr++;
+  }
+}
+
+/**
+  Get padding resource for PCI-PCI bridge.
+
+  @param  PciIoDevice     PCI-PCI bridge device instance.
+
+  @note   Feature flag PcdPciBusHotplugDeviceSupport determines
+          whether need to pad resource for them.
+**/
+VOID
+GetResourcePaddingPpb (
+  IN  PCI_IO_DEVICE                  *PciIoDevice
+  )
+{
+  if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
+    if (PciIoDevice->ResourcePaddingDescriptors == NULL) {
+      GetResourcePaddingForHpb (PciIoDevice);
+    }
+  }
+}
+
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h
new file mode 100644
index 0000000000..2a33f77e55
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h
@@ -0,0 +1,456 @@
+/** @file
+  PCI resources support functions declaration for PCI Bus module.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_PCI_RESOURCE_SUPPORT_H_
+#define _EFI_PCI_RESOURCE_SUPPORT_H_
+
+typedef enum {
+  PciResUsageTypical,
+  PciResUsagePadding
+} PCI_RESOURCE_USAGE;
+
+#define PCI_RESOURCE_SIGNATURE  SIGNATURE_32 ('p', 'c', 'r', 'c')
+
+typedef struct {
+  UINT32              Signature;
+  LIST_ENTRY          Link;
+  LIST_ENTRY          ChildList;
+  PCI_IO_DEVICE       *PciDev;
+  UINT64              Alignment;
+  UINT64              Offset;
+  UINT8               Bar;
+  PCI_BAR_TYPE        ResType;
+  UINT64              Length;
+  BOOLEAN             Reserved;
+  PCI_RESOURCE_USAGE  ResourceUsage;
+  BOOLEAN             Virtual;
+} PCI_RESOURCE_NODE;
+
+#define RESOURCE_NODE_FROM_LINK(a) \
+  CR (a, PCI_RESOURCE_NODE, Link, PCI_RESOURCE_SIGNATURE)
+
+/**
+  The function is used to skip VGA range.
+
+  @param Start    Returned start address including VGA range.
+  @param Length   The length of VGA range.
+
+**/
+VOID
+SkipVGAAperture (
+  OUT UINT64   *Start,
+  IN  UINT64   Length
+  );
+
+/**
+  This function is used to skip ISA aliasing aperture.
+
+  @param Start    Returned start address including ISA aliasing aperture.
+  @param Length   The length of ISA aliasing aperture.
+
+**/
+VOID
+SkipIsaAliasAperture (
+  OUT UINT64   *Start,
+  IN  UINT64   Length
+  );
+
+/**
+  This function inserts a resource node into the resource list.
+  The resource list is sorted in descend order.
+
+  @param Bridge  PCI resource node for bridge.
+  @param ResNode Resource node want to be inserted.
+
+**/
+VOID
+InsertResourceNode (
+  IN OUT PCI_RESOURCE_NODE   *Bridge,
+  IN     PCI_RESOURCE_NODE   *ResNode
+  );
+
+/**
+  This routine is used to merge two different resource trees in need of
+  resource degradation.
+
+  For example, if an upstream PPB doesn't support,
+  prefetchable memory decoding, the PCI bus driver will choose to call this function
+  to merge prefetchable memory resource list into normal memory list.
+
+  If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource
+  type.
+  If Dst is NULL or Res is NULL, ASSERT ().
+
+  @param Dst        Point to destination resource tree.
+  @param Res        Point to source resource tree.
+  @param TypeMerge  If the TypeMerge is TRUE, Res resource type is changed to the type of
+                    destination resource type.
+
+**/
+VOID
+MergeResourceTree (
+  IN PCI_RESOURCE_NODE   *Dst,
+  IN PCI_RESOURCE_NODE   *Res,
+  IN BOOLEAN             TypeMerge
+  );
+
+/**
+  This function is used to calculate the IO16 aperture
+  for a bridge.
+
+  @param Bridge    PCI resource node for bridge.
+
+**/
+VOID
+CalculateApertureIo16 (
+  IN PCI_RESOURCE_NODE    *Bridge
+  );
+
+/**
+  This function is used to calculate the resource aperture
+  for a given bridge device.
+
+  @param Bridge      PCI resource node for given bridge device.
+
+**/
+VOID
+CalculateResourceAperture (
+  IN PCI_RESOURCE_NODE    *Bridge
+  );
+
+/**
+  Get IO/Memory resource info for given PCI device.
+
+  @param PciDev     Pci device instance.
+  @param IoNode     Resource info node for IO .
+  @param Mem32Node  Resource info node for 32-bit memory.
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
+  @param Mem64Node  Resource info node for 64-bit memory.
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
+
+**/
+VOID
+GetResourceFromDevice (
+  IN     PCI_IO_DEVICE     *PciDev,
+  IN OUT PCI_RESOURCE_NODE *IoNode,
+  IN OUT PCI_RESOURCE_NODE *Mem32Node,
+  IN OUT PCI_RESOURCE_NODE *PMem32Node,
+  IN OUT PCI_RESOURCE_NODE *Mem64Node,
+  IN OUT PCI_RESOURCE_NODE *PMem64Node
+  );
+
+/**
+  This function is used to create a resource node.
+
+  @param PciDev       Pci device instance.
+  @param Length       Length of Io/Memory resource.
+  @param Alignment    Alignment of resource.
+  @param Bar          Bar index.
+  @param ResType      Type of resource: IO/Memory.
+  @param ResUsage     Resource usage.
+
+  @return PCI resource node created for given PCI device.
+          NULL means PCI resource node is not created.
+
+**/
+PCI_RESOURCE_NODE *
+CreateResourceNode (
+  IN PCI_IO_DEVICE         *PciDev,
+  IN UINT64                Length,
+  IN UINT64                Alignment,
+  IN UINT8                 Bar,
+  IN PCI_BAR_TYPE          ResType,
+  IN PCI_RESOURCE_USAGE    ResUsage
+  );
+
+/**
+  This function is used to create a IOV VF resource node.
+
+  @param PciDev       Pci device instance.
+  @param Length       Length of Io/Memory resource.
+  @param Alignment    Alignment of resource.
+  @param Bar          Bar index.
+  @param ResType      Type of resource: IO/Memory.
+  @param ResUsage     Resource usage.
+
+  @return PCI resource node created for given VF PCI device.
+          NULL means PCI resource node is not created.
+
+**/
+PCI_RESOURCE_NODE *
+CreateVfResourceNode (
+  IN PCI_IO_DEVICE         *PciDev,
+  IN UINT64                Length,
+  IN UINT64                Alignment,
+  IN UINT8                 Bar,
+  IN PCI_BAR_TYPE          ResType,
+  IN PCI_RESOURCE_USAGE    ResUsage
+  );
+
+/**
+  This function is used to extract resource request from
+  device node list.
+
+  @param Bridge     Pci device instance.
+  @param IoNode     Resource info node for IO.
+  @param Mem32Node  Resource info node for 32-bit memory.
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
+  @param Mem64Node  Resource info node for 64-bit memory.
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
+
+**/
+VOID
+CreateResourceMap (
+  IN     PCI_IO_DEVICE     *Bridge,
+  IN OUT PCI_RESOURCE_NODE *IoNode,
+  IN OUT PCI_RESOURCE_NODE *Mem32Node,
+  IN OUT PCI_RESOURCE_NODE *PMem32Node,
+  IN OUT PCI_RESOURCE_NODE *Mem64Node,
+  IN OUT PCI_RESOURCE_NODE *PMem64Node
+  );
+
+/**
+  This function is used to do the resource padding for a specific platform.
+
+  @param PciDev     Pci device instance.
+  @param IoNode     Resource info node for IO.
+  @param Mem32Node  Resource info node for 32-bit memory.
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
+  @param Mem64Node  Resource info node for 64-bit memory.
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
+
+**/
+VOID
+ResourcePaddingPolicy (
+  IN PCI_IO_DEVICE     *PciDev,
+  IN PCI_RESOURCE_NODE *IoNode,
+  IN PCI_RESOURCE_NODE *Mem32Node,
+  IN PCI_RESOURCE_NODE *PMem32Node,
+  IN PCI_RESOURCE_NODE *Mem64Node,
+  IN PCI_RESOURCE_NODE *PMem64Node
+  );
+
+/**
+  This function is used to degrade resource if the upstream bridge
+  doesn't support certain resource. Degradation path is
+  PMEM64 -> MEM64  -> MEM32
+  PMEM64 -> PMEM32 -> MEM32
+  IO32   -> IO16.
+
+  @param Bridge     Pci device instance.
+  @param Mem32Node  Resource info node for 32-bit memory.
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
+  @param Mem64Node  Resource info node for 64-bit memory.
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
+
+**/
+VOID
+DegradeResource (
+  IN PCI_IO_DEVICE     *Bridge,
+  IN PCI_RESOURCE_NODE *Mem32Node,
+  IN PCI_RESOURCE_NODE *PMem32Node,
+  IN PCI_RESOURCE_NODE *Mem64Node,
+  IN PCI_RESOURCE_NODE *PMem64Node
+  );
+
+/**
+  Test whether bridge device support decode resource.
+
+  @param Bridge    Bridge device instance.
+  @param Decode    Decode type according to resource type.
+
+  @return TRUE     The bridge device support decode resource.
+  @return FALSE    The bridge device don't support decode resource.
+
+**/
+BOOLEAN
+BridgeSupportResourceDecode (
+  IN PCI_IO_DEVICE *Bridge,
+  IN UINT32        Decode
+  );
+
+/**
+  This function is used to program the resource allocated
+  for each resource node under specified bridge.
+
+  @param Base     Base address of resource to be programmed.
+  @param Bridge   PCI resource node for the bridge device.
+
+  @retval EFI_SUCCESS            Successfully to program all resources
+                                 on given PCI bridge device.
+  @retval EFI_OUT_OF_RESOURCES   Base is all one.
+
+**/
+EFI_STATUS
+ProgramResource (
+  IN UINT64            Base,
+  IN PCI_RESOURCE_NODE *Bridge
+  );
+
+/**
+  Program Bar register for PCI device.
+
+  @param Base  Base address for PCI device resource to be programmed.
+  @param Node  Point to resource node structure.
+
+**/
+VOID
+ProgramBar (
+  IN UINT64            Base,
+  IN PCI_RESOURCE_NODE *Node
+  );
+
+/**
+  Program IOV VF Bar register for PCI device.
+
+  @param Base  Base address for PCI device resource to be programmed.
+  @param Node  Point to resource node structure.
+
+**/
+EFI_STATUS
+ProgramVfBar (
+  IN UINT64            Base,
+  IN PCI_RESOURCE_NODE *Node
+  );
+
+/**
+  Program PCI-PCI bridge aperture.
+
+  @param Base  Base address for resource.
+  @param Node  Point to resource node structure.
+
+**/
+VOID
+ProgramPpbApperture (
+  IN UINT64            Base,
+  IN PCI_RESOURCE_NODE *Node
+  );
+
+/**
+  Program parent bridge for Option Rom.
+
+  @param PciDevice      Pci device instance.
+  @param OptionRomBase  Base address for Option Rom.
+  @param Enable         Enable or disable PCI memory.
+
+**/
+VOID
+ProgramUpstreamBridgeForRom (
+  IN PCI_IO_DEVICE   *PciDevice,
+  IN UINT32          OptionRomBase,
+  IN BOOLEAN         Enable
+  );
+
+/**
+  Test whether resource exists for a bridge.
+
+  @param Bridge  Point to resource node for a bridge.
+
+  @retval TRUE   There is resource on the given bridge.
+  @retval FALSE  There isn't resource on the given bridge.
+
+**/
+BOOLEAN
+ResourceRequestExisted (
+  IN PCI_RESOURCE_NODE    *Bridge
+  );
+
+/**
+  Initialize resource pool structure.
+
+  @param ResourcePool Point to resource pool structure. This pool
+                      is reset to all zero when returned.
+  @param ResourceType Type of resource.
+
+**/
+VOID
+InitializeResourcePool (
+  IN OUT PCI_RESOURCE_NODE   *ResourcePool,
+  IN     PCI_BAR_TYPE        ResourceType
+  );
+
+/**
+  Destroy given resource tree.
+
+  @param Bridge  PCI resource root node of resource tree.
+
+**/
+VOID
+DestroyResourceTree (
+  IN PCI_RESOURCE_NODE *Bridge
+  );
+
+/**
+  Insert resource padding for P2C.
+
+  @param PciDev     Pci device instance.
+  @param IoNode     Resource info node for IO.
+  @param Mem32Node  Resource info node for 32-bit memory.
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
+  @param Mem64Node  Resource info node for 64-bit memory.
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
+
+**/
+VOID
+ResourcePaddingForCardBusBridge (
+  IN PCI_IO_DEVICE        *PciDev,
+  IN PCI_RESOURCE_NODE    *IoNode,
+  IN PCI_RESOURCE_NODE    *Mem32Node,
+  IN PCI_RESOURCE_NODE    *PMem32Node,
+  IN PCI_RESOURCE_NODE    *Mem64Node,
+  IN PCI_RESOURCE_NODE    *PMem64Node
+  );
+
+/**
+  Program PCI Card device register for given resource node.
+
+  @param Base    Base address of PCI Card device to be programmed.
+  @param Node    Given resource node.
+
+**/
+VOID
+ProgramP2C (
+  IN UINT64            Base,
+  IN PCI_RESOURCE_NODE *Node
+  );
+
+/**
+  Create padding resource node.
+
+  @param PciDev     Pci device instance.
+  @param IoNode     Resource info node for IO.
+  @param Mem32Node  Resource info node for 32-bit memory.
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
+  @param Mem64Node  Resource info node for 64-bit memory.
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
+
+**/
+VOID
+ApplyResourcePadding (
+  IN PCI_IO_DEVICE         *PciDev,
+  IN PCI_RESOURCE_NODE     *IoNode,
+  IN PCI_RESOURCE_NODE     *Mem32Node,
+  IN PCI_RESOURCE_NODE     *PMem32Node,
+  IN PCI_RESOURCE_NODE     *Mem64Node,
+  IN PCI_RESOURCE_NODE     *PMem64Node
+  );
+
+/**
+  Get padding resource for PCI-PCI bridge.
+
+  @param  PciIoDevice     PCI-PCI bridge device instance.
+
+  @note   Feature flag PcdPciBusHotplugDeviceSupport determines
+          whether need to pad resource for them.
+**/
+VOID
+GetResourcePaddingPpb (
+  IN  PCI_IO_DEVICE                  *PciIoDevice
+  );
+
+#endif
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.c
new file mode 100644
index 0000000000..507aed5cfe
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.c
@@ -0,0 +1,135 @@
+/** @file
+  Set up ROM Table for PCI Bus module.
+
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+
+//
+// PCI ROM image information
+//
+typedef struct {
+  EFI_HANDLE  ImageHandle;
+  UINTN       Seg;
+  UINT8       Bus;
+  UINT8       Dev;
+  UINT8       Func;
+  VOID        *RomImage;
+  UINT64      RomSize;
+} PCI_ROM_IMAGE;
+
+UINTN          mNumberOfPciRomImages     = 0;
+UINTN          mMaxNumberOfPciRomImages  = 0;
+PCI_ROM_IMAGE  *mRomImageTable           = NULL;
+
+/**
+  Add the Rom Image to internal database for later PCI light enumeration.
+
+  @param ImageHandle    Option Rom image handle.
+  @param Seg            Segment of PCI space.
+  @param Bus            Bus NO of PCI space.
+  @param Dev            Dev NO of PCI space.
+  @param Func           Func NO of PCI space.
+  @param RomImage       Option Rom buffer.
+  @param RomSize        Size of Option Rom buffer.
+**/
+VOID
+PciRomAddImageMapping (
+  IN  EFI_HANDLE  ImageHandle,
+  IN  UINTN       Seg,
+  IN  UINT8       Bus,
+  IN  UINT8       Dev,
+  IN  UINT8       Func,
+  IN  VOID        *RomImage,
+  IN  UINT64      RomSize
+  )
+{
+  UINTN           Index;
+  PCI_ROM_IMAGE   *NewTable;
+
+  for (Index = 0; Index < mNumberOfPciRomImages; Index++) {
+    if (mRomImageTable[Index].Seg  == Seg &&
+        mRomImageTable[Index].Bus  == Bus &&
+        mRomImageTable[Index].Dev  == Dev &&
+        mRomImageTable[Index].Func == Func) {
+      //
+      // Expect once RomImage and RomSize are recorded, they will be passed in
+      // later when updating ImageHandle
+      //
+      ASSERT ((mRomImageTable[Index].RomImage == NULL) || (RomImage == mRomImageTable[Index].RomImage));
+      ASSERT ((mRomImageTable[Index].RomSize  == 0   ) || (RomSize  == mRomImageTable[Index].RomSize ));
+      break;
+    }
+  }
+
+  if (Index == mNumberOfPciRomImages) {
+    //
+    // Rom Image Table buffer needs to grow.
+    //
+    if (mNumberOfPciRomImages == mMaxNumberOfPciRomImages) {
+      NewTable = ReallocatePool (
+                   mMaxNumberOfPciRomImages * sizeof (PCI_ROM_IMAGE),
+                   (mMaxNumberOfPciRomImages + 0x20) * sizeof (PCI_ROM_IMAGE),
+                   mRomImageTable
+                   );
+      if (NewTable == NULL) {
+        return ;
+      }
+
+      mRomImageTable            = NewTable;
+      mMaxNumberOfPciRomImages += 0x20;
+    }
+    //
+    // Record the new PCI device
+    //
+    mRomImageTable[Index].Seg  = Seg;
+    mRomImageTable[Index].Bus  = Bus;
+    mRomImageTable[Index].Dev  = Dev;
+    mRomImageTable[Index].Func = Func;
+    mNumberOfPciRomImages++;
+  }
+
+  mRomImageTable[Index].ImageHandle = ImageHandle;
+  mRomImageTable[Index].RomImage    = RomImage;
+  mRomImageTable[Index].RomSize     = RomSize;
+}
+
+/**
+  Get Option rom driver's mapping for PCI device.
+
+  @param PciIoDevice Device instance.
+
+  @retval TRUE   Found Image mapping.
+  @retval FALSE  Cannot found image mapping.
+
+**/
+BOOLEAN
+PciRomGetImageMapping (
+  IN  PCI_IO_DEVICE                       *PciIoDevice
+  )
+{
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+  UINTN                           Index;
+
+  PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;
+
+  for (Index = 0; Index < mNumberOfPciRomImages; Index++) {
+    if (mRomImageTable[Index].Seg  == PciRootBridgeIo->SegmentNumber &&
+        mRomImageTable[Index].Bus  == PciIoDevice->BusNumber         &&
+        mRomImageTable[Index].Dev  == PciIoDevice->DeviceNumber      &&
+        mRomImageTable[Index].Func == PciIoDevice->FunctionNumber    ) {
+
+      if (mRomImageTable[Index].ImageHandle != NULL) {
+        AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle, NULL);
+      }
+      PciIoDevice->PciIo.RomImage = mRomImageTable[Index].RomImage;
+      PciIoDevice->PciIo.RomSize  = mRomImageTable[Index].RomSize;
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.h
new file mode 100644
index 0000000000..fb356bd6de
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.h
@@ -0,0 +1,48 @@
+/** @file
+  Set up ROM Table for PCI Bus module.
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_PCI_ROM_TABLE_H_
+#define _EFI_PCI_ROM_TABLE_H_
+
+/**
+  Add the Rom Image to internal database for later PCI light enumeration.
+
+  @param ImageHandle    Option Rom image handle.
+  @param Seg            Segment of PCI space.
+  @param Bus            Bus NO of PCI space.
+  @param Dev            Dev NO of PCI space.
+  @param Func           Func NO of PCI space.
+  @param RomImage       Option Rom buffer.
+  @param RomSize        Size of Option Rom buffer.
+**/
+VOID
+PciRomAddImageMapping (
+  IN  EFI_HANDLE  ImageHandle,
+  IN  UINTN       Seg,
+  IN  UINT8       Bus,
+  IN  UINT8       Dev,
+  IN  UINT8       Func,
+  IN  VOID        *RomImage,
+  IN  UINT64      RomSize
+  );
+
+/**
+  Get Option rom driver's mapping for PCI device.
+
+  @param PciIoDevice Device instance.
+
+  @retval TRUE   Found Image mapping.
+  @retval FALSE  Cannot found image mapping.
+
+**/
+BOOLEAN
+PciRomGetImageMapping (
+  IN  PCI_IO_DEVICE                       *PciIoDevice
+  );
+
+#endif
--
2.25.0.windows.1


Please consider the environment before printing this email.

The information contained in this message may be confidential and proprietary to American Megatrends (AMI).  This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited.  Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.
GitPatchExtractor 1.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with
  2021-06-17 14:55   ` [EXTERNAL] " manickavasakam karpagavinayagam
@ 2021-06-17 15:19     ` Michael D Kinney
  2021-06-17 16:41       ` manickavasakam karpagavinayagam
  0 siblings, 1 reply; 7+ messages in thread
From: Michael D Kinney @ 2021-06-17 15:19 UTC (permalink / raw)
  To: devel@edk2.groups.io, KARPAGAVINAYAGAM, MANICKAVASAKAM, gaoliming,
	Ni, Ray, Kinney, Michael D
  Cc: DOPPALAPUDI, HARIKRISHNA

[-- Attachment #1: Type: text/plain, Size: 15969 bytes --]

Has the reason for the PciBusDxe override been discussed with the PciBusDxe maintainer?

What feature would need to be added to PciBusDxe to accommodate the use case?

Mike

From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of manickavasakam karpagavinayagam
Sent: Thursday, June 17, 2021 7:56 AM
To: gaoliming <gaoliming@byosoft.com.cn>; devel@edk2.groups.io
Cc: DOPPALAPUDI, HARIKRISHNA <harikrishnad@ami.com>
Subject: Re: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with

Liming :

Below email is the cover letter and this patch series has two changes. Sure next time, will add more comments in the cover letter also.
Please refer the attached email and it has information about the PCIBUS override changes. PCIBUS override is done based on the platform sighting and it can’t be generic.

Thank you

-Manic

From: gaoliming <gaoliming@byosoft.com.cn<mailto:gaoliming@byosoft.com.cn>>
Sent: Wednesday, June 16, 2021 10:56 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Manickavasakam Karpagavinayagam <manickavasakamk@ami.com<mailto:manickavasakamk@ami.com>>
Subject: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with


**CAUTION: The e-mail below is from an external source. Please exercise caution before opening attachments, clicking links, or following guidance.**

Please follow https://github.com/tianocore/tianocore.github.io/wiki/Commit-Message-Format<https://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FCommit-Message-Format&data=04%7C01%7Cmanickavasakamk%40ami.com%7C478d38ff236a496b1f8a08d9313b78b5%7C27e97857e15f486cb58e86c2b3040f93%7C1%7C0%7C637594953779151841%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=RhP%2BBy62unxjQauvze06TjzReq%2FJfUgq7%2B9DR0R8kNY%3D&reserved=0> to update the commit message format.

And, for the override PciBus module, can you give more detail why need to override PciBus? Is it possible to update Edk2 MdeModulePkg PciBus to meet the platform requirement?

Thanks
Liming
发件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> 代表 manickavasakam karpagavinayagam
发送时间: 2021年6月17日 7:05
收件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
主题: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with


Add BoardTiogaPass packages to support TiogaPass Platform Enabled Network, ISCSI,IPMI, SMBIOS, Performance Measurement
Remove AST2500 UEFI option ROM driver from PurleyOpenBoardPkg

AST2500 UEFI option ROM move to edk2-non-osi ASpeedGopBinPkg Update copyright headers



manickavasakam karpagavinayagam (2):

  PurleyOpenBoardPkg : Support for TiogaPass Platform

  PurleyOpenBoardPkg : Override generic PciBus Driver with Platform

    specific instance of PciBus driver.



.../IpmiFeaturePkg/GenericIpmi/Dxe/IpmiInit.c |    8 +-

.../Acpi/BoardAcpiDxe/AmlOffsetTable.c        |  453 +-

.../Acpi/BoardAcpiDxe/BoardAcpiDxeDsdt.c      |    3 +

.../BoardTiogaPass/CoreDxeInclude.dsc         |  168 +

.../BoardTiogaPass/CoreUefiBootInclude.fdf    |   82 +

.../BoardTiogaPass/GitEdk2MinTiogaPass.bat    |   93 +

.../BasePlatformHookLib/BasePlatformHookLib.c |  389 +

.../BasePlatformHookLib.inf                   |   36 +

.../BoardAcpiLib/DxeBoardAcpiTableLib.c       |   36 +

.../BoardAcpiLib/DxeBoardAcpiTableLib.inf     |   40 +

.../BoardAcpiLib/DxeTiogaPassAcpiTableLib.c   |   53 +

.../BoardAcpiLib/SmmBoardAcpiEnableLib.c      |   62 +

.../BoardAcpiLib/SmmBoardAcpiEnableLib.inf    |   41 +

.../BoardAcpiLib/SmmSiliconAcpiEnableLib.c    |  120 +

.../BoardAcpiLib/SmmTiogaPassAcpiEnableLib.c  |   37 +

.../Library/BoardInitLib/AllLanesEparam.c     |   44 +

.../Library/BoardInitLib/GpioTable.c          |  296 +

.../Library/BoardInitLib/IioBifur.c           |   70 +

.../BoardInitLib/PeiBoardInitPostMemLib.c     |   46 +

.../BoardInitLib/PeiBoardInitPostMemLib.inf   |   37 +

.../BoardInitLib/PeiBoardInitPreMemLib.c      |  112 +

.../BoardInitLib/PeiBoardInitPreMemLib.inf    |   69 +

.../Library/BoardInitLib/PeiTiogaPassDetect.c |   28 +

.../BoardInitLib/PeiTiogaPassInitLib.h        |   18 +

.../BoardInitLib/PeiTiogaPassInitPostMemLib.c |   86 +

.../BoardInitLib/PeiTiogaPassInitPreMemLib.c  |  638 ++

.../Library/BoardInitLib/UsbOC.c              |   46 +

.../Library/PeiReportFvLib/PeiReportFvLib.c   |  138 +

.../Library/PeiReportFvLib/PeiReportFvLib.inf |   51 +

.../BoardTiogaPass/OpenBoardPkg.dsc           |  245 +

.../BoardTiogaPass/OpenBoardPkg.fdf           |  600 ++

.../BoardTiogaPass/PlatformPkgBuildOption.dsc |   84 +

.../BoardTiogaPass/PlatformPkgConfig.dsc      |   58 +

.../BoardTiogaPass/PlatformPkgPcd.dsc         |  392 ++

.../BoardTiogaPass/StructureConfig.dsc        | 6236 +++++++++++++++++

.../BoardTiogaPass/__init__.py                |    0

.../PurleyOpenBoardPkg/BoardTiogaPass/bld.bat |  139 +

.../BoardTiogaPass/build_board.py             |  195 +

.../BoardTiogaPass/build_config.cfg           |   34 +

.../BoardTiogaPass/logo.txt                   |   10 +

.../BoardTiogaPass/postbuild.bat              |   96 +

.../BoardTiogaPass/prebuild.bat               |  213 +

.../Ipmi/Library/IpmiLibKcs/IpmiLibKcs.inf    |   10 +-

.../IpmiPlatformHookLib.inf                   |    6 +-

.../Include/Guid/PchRcVariable.h              |    6 +

.../Include/Guid/SetupVariable.h              |   15 +-

.../Intel/PurleyOpenBoardPkg/OpenBoardPkg.dec |    1 +

.../Bus/Pci/PciBusDxe/ComponentName.c         |  170 +

.../Bus/Pci/PciBusDxe/ComponentName.h         |  146 +

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c   |  460 ++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h   |  396 ++

.../Bus/Pci/PciBusDxe/PciBusDxe.inf           |  112 +

.../Bus/Pci/PciBusDxe/PciBusDxe.uni           |   16 +

.../Bus/Pci/PciBusDxe/PciBusDxeExtra.uni      |   14 +

.../Bus/Pci/PciBusDxe/PciCommand.c            |  267 +

.../Bus/Pci/PciBusDxe/PciCommand.h            |  232 +

.../Bus/Pci/PciBusDxe/PciDeviceSupport.c      | 1056 +++

.../Bus/Pci/PciBusDxe/PciDeviceSupport.h      |  266 +

.../Bus/Pci/PciBusDxe/PciDriverOverride.c     |  188 +

.../Bus/Pci/PciBusDxe/PciDriverOverride.h     |   83 +

.../Bus/Pci/PciBusDxe/PciEnumerator.c         | 2210 ++++++

.../Bus/Pci/PciBusDxe/PciEnumerator.h         |  515 ++

.../Bus/Pci/PciBusDxe/PciEnumeratorSupport.c  | 2885 ++++++++  .../Bus/Pci/PciBusDxe/PciEnumeratorSupport.h  |  480 ++

.../Bus/Pci/PciBusDxe/PciHotPlugSupport.c     |  484 ++

.../Bus/Pci/PciBusDxe/PciHotPlugSupport.h     |  205 +

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c    | 2087 ++++++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h    |  660 ++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c   | 1809 +++++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h   |  179 +

.../Bus/Pci/PciBusDxe/PciOptionRomSupport.c   |  776 ++

.../Bus/Pci/PciBusDxe/PciOptionRomSupport.h   |  136 +

.../Bus/Pci/PciBusDxe/PciPowerManagement.c    |   82 +

.../Bus/Pci/PciBusDxe/PciPowerManagement.h    |   28 +

.../Bus/Pci/PciBusDxe/PciResourceSupport.c    | 2292 ++++++

.../Bus/Pci/PciBusDxe/PciResourceSupport.h    |  456 ++

.../Bus/Pci/PciBusDxe/PciRomTable.c           |  135 +

.../Bus/Pci/PciBusDxe/PciRomTable.h           |   48 +

Platform/Intel/build.cfg                      |    2 +

Platform/Intel/build_bios.py                  |    3 +-

80 files changed, 30278 insertions(+), 240 deletions(-)  create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreDxeInclude.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootInclude.fdf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/GitEdk2MinTiogaPass.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BasePlatformHookLib/BasePlatformHookLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BasePlatformHookLib/BasePlatformHookLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeBoardAcpiTableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeBoardAcpiTableLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeTiogaPassAcpiTableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmBoardAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmBoardAcpiEnableLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmSiliconAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmTiogaPassAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/AllLanesEparam.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/GpioTable.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/IioBifur.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPostMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPostMemLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPreMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPreMemLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassDetect.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitLib.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitPostMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitPreMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/UsbOC.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/PeiReportFvLib/PeiReportFvLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/PeiReportFvLib/PeiReportFvLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/OpenBoardPkg.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/OpenBoardPkg.fdf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgBuildOption.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgConfig.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgPcd.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/StructureConfig.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/__init__.py

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/bld.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/build_board.py

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/build_config.cfg

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/logo.txt

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/postbuild.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/prebuild.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.uni

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxeExtra.uni

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.h
-The information contained in this message may be confidential and proprietary to American Megatrends (AMI). This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited. Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.


[-- Attachment #2: Type: text/html, Size: 71457 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with
  2021-06-17 15:19     ` Michael D Kinney
@ 2021-06-17 16:41       ` manickavasakam karpagavinayagam
  2021-06-18  6:11         ` Ni, Ray
  0 siblings, 1 reply; 7+ messages in thread
From: manickavasakam karpagavinayagam @ 2021-06-17 16:41 UTC (permalink / raw)
  To: Kinney, Michael D, devel@edk2.groups.io, gaoliming, Ni, Ray
  Cc: Harikrishna Doppalapudi

[-- Attachment #1: Type: text/plain, Size: 19277 bytes --]

Mike :

During PCI Bus enumeration, we need to skip SPI Controller (because of a silicon sighting) or else any SET variable asserts.
Also, need to skip a specific MLX card UEFI OPROM or else will see CPU exception.

We checked the PCIBUS driver code flow and there is no generic hooks to skip enumerating a device and to override the OPROM contents.

To avoid overriding the PCIBUS driver with platform instance, we can have PciBus Hooks at various places in PCIBUS driver to skip the device from enumeration, overriding the OPROM contents etc..

Ex : MdeModulePkg\Bus\Pci\PciBusDxe\PciLib.c PciScanBus()

        for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
    TempReservedBusNum = 0;
    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {

      //
      // Check to see whether a pci device is present
      //
      Status = PciDevicePresent (
                PciRootBridgeIo,
                &Pci,
                StartBusNumber,
                Device,
                Func
                );

      if (EFI_ERROR (Status) && Func == 0) {
        //
        // go to next device if there is no Function 0
        //
        break;
      }

      if (EFI_ERROR (Status)) {
        continue;
      }


      Status = PciOemPlatformHooks(&Pci, isPciSkipDevice, &Pci, &StartBusNumber, &Device, &Func);
      if(EFI_ERROR(Status))
      {
          if(Status==EFI_UNSUPPORTED){
              Status=EFI_SUCCESS;
          } else ASSERT_EFI_ERROR(Status);
      }
      else
      {
          DEBUG((DEBUG_INFO,"Device @ [B%X|D%X|F%X], VID=%X, DID=%X SKIPPED from enumeration.\n\n",
                  StartBusNumber, Device, Func,
                  Pci.Hdr.VendorId,Pci.Hdr.DeviceId));
          continue;
      }

      //
      // Get the PCI device information
      //
      Status = PciSearchDevice (
                Bridge,
                &Pci,
                StartBusNumber,
                Device,
                Func,
                &PciDevice
                );

      if (EFI_ERROR (Status)) {
        continue;
      }

Thank you

-Manic

From: Kinney, Michael D <michael.d.kinney@intel.com>
Sent: Thursday, June 17, 2021 11:19 AM
To: devel@edk2.groups.io; Manickavasakam Karpagavinayagam <manickavasakamk@ami.com>; gaoliming <gaoliming@byosoft.com.cn>; Ni, Ray <ray.ni@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Harikrishna Doppalapudi <Harikrishnad@ami.com>
Subject: RE: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with

Has the reason for the PciBusDxe override been discussed with the PciBusDxe maintainer?

What feature would need to be added to PciBusDxe to accommodate the use case?

Mike

From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> On Behalf Of manickavasakam karpagavinayagam
Sent: Thursday, June 17, 2021 7:56 AM
To: gaoliming <gaoliming@byosoft.com.cn<mailto:gaoliming@byosoft.com.cn>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>
Cc: DOPPALAPUDI, HARIKRISHNA <harikrishnad@ami.com<mailto:harikrishnad@ami.com>>
Subject: Re: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with

Liming :

Below email is the cover letter and this patch series has two changes. Sure next time, will add more comments in the cover letter also.
Please refer the attached email and it has information about the PCIBUS override changes. PCIBUS override is done based on the platform sighting and it can’t be generic.

Thank you

-Manic

From: gaoliming <gaoliming@byosoft.com.cn<mailto:gaoliming@byosoft.com.cn>>
Sent: Wednesday, June 16, 2021 10:56 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Manickavasakam Karpagavinayagam <manickavasakamk@ami.com<mailto:manickavasakamk@ami.com>>
Subject: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with


**CAUTION: The e-mail below is from an external source. Please exercise caution before opening attachments, clicking links, or following guidance.**

Please follow https://github.com/tianocore/tianocore.github.io/wiki/Commit-Message-Format<https://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FCommit-Message-Format&data=04%7C01%7Cmanickavasakamk%40ami.com%7Cf76e7f29b16b4cf90ec908d931a340b2%7C27e97857e15f486cb58e86c2b3040f93%7C1%7C0%7C637595399503823678%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=w%2BRgvWwnXJy1wlN%2F%2Bbr9zvlp2etWRHhRRuiie7mViRA%3D&reserved=0> to update the commit message format.

And, for the override PciBus module, can you give more detail why need to override PciBus? Is it possible to update Edk2 MdeModulePkg PciBus to meet the platform requirement?

Thanks
Liming
发件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> 代表 manickavasakam karpagavinayagam
发送时间: 2021年6月17日 7:05
收件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
主题: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with


Add BoardTiogaPass packages to support TiogaPass Platform Enabled Network, ISCSI,IPMI, SMBIOS, Performance Measurement
Remove AST2500 UEFI option ROM driver from PurleyOpenBoardPkg

AST2500 UEFI option ROM move to edk2-non-osi ASpeedGopBinPkg Update copyright headers



manickavasakam karpagavinayagam (2):

  PurleyOpenBoardPkg : Support for TiogaPass Platform

  PurleyOpenBoardPkg : Override generic PciBus Driver with Platform

    specific instance of PciBus driver.



.../IpmiFeaturePkg/GenericIpmi/Dxe/IpmiInit.c |    8 +-

.../Acpi/BoardAcpiDxe/AmlOffsetTable.c        |  453 +-

.../Acpi/BoardAcpiDxe/BoardAcpiDxeDsdt.c      |    3 +

.../BoardTiogaPass/CoreDxeInclude.dsc         |  168 +

.../BoardTiogaPass/CoreUefiBootInclude.fdf    |   82 +

.../BoardTiogaPass/GitEdk2MinTiogaPass.bat    |   93 +

.../BasePlatformHookLib/BasePlatformHookLib.c |  389 +

.../BasePlatformHookLib.inf                   |   36 +

.../BoardAcpiLib/DxeBoardAcpiTableLib.c       |   36 +

.../BoardAcpiLib/DxeBoardAcpiTableLib.inf     |   40 +

.../BoardAcpiLib/DxeTiogaPassAcpiTableLib.c   |   53 +

.../BoardAcpiLib/SmmBoardAcpiEnableLib.c      |   62 +

.../BoardAcpiLib/SmmBoardAcpiEnableLib.inf    |   41 +

.../BoardAcpiLib/SmmSiliconAcpiEnableLib.c    |  120 +

.../BoardAcpiLib/SmmTiogaPassAcpiEnableLib.c  |   37 +

.../Library/BoardInitLib/AllLanesEparam.c     |   44 +

.../Library/BoardInitLib/GpioTable.c          |  296 +

.../Library/BoardInitLib/IioBifur.c           |   70 +

.../BoardInitLib/PeiBoardInitPostMemLib.c     |   46 +

.../BoardInitLib/PeiBoardInitPostMemLib.inf   |   37 +

.../BoardInitLib/PeiBoardInitPreMemLib.c      |  112 +

.../BoardInitLib/PeiBoardInitPreMemLib.inf    |   69 +

.../Library/BoardInitLib/PeiTiogaPassDetect.c |   28 +

.../BoardInitLib/PeiTiogaPassInitLib.h        |   18 +

.../BoardInitLib/PeiTiogaPassInitPostMemLib.c |   86 +

.../BoardInitLib/PeiTiogaPassInitPreMemLib.c  |  638 ++

.../Library/BoardInitLib/UsbOC.c              |   46 +

.../Library/PeiReportFvLib/PeiReportFvLib.c   |  138 +

.../Library/PeiReportFvLib/PeiReportFvLib.inf |   51 +

.../BoardTiogaPass/OpenBoardPkg.dsc           |  245 +

.../BoardTiogaPass/OpenBoardPkg.fdf           |  600 ++

.../BoardTiogaPass/PlatformPkgBuildOption.dsc |   84 +

.../BoardTiogaPass/PlatformPkgConfig.dsc      |   58 +

.../BoardTiogaPass/PlatformPkgPcd.dsc         |  392 ++

.../BoardTiogaPass/StructureConfig.dsc        | 6236 +++++++++++++++++

.../BoardTiogaPass/__init__.py                |    0

.../PurleyOpenBoardPkg/BoardTiogaPass/bld.bat |  139 +

.../BoardTiogaPass/build_board.py             |  195 +

.../BoardTiogaPass/build_config.cfg           |   34 +

.../BoardTiogaPass/logo.txt                   |   10 +

.../BoardTiogaPass/postbuild.bat              |   96 +

.../BoardTiogaPass/prebuild.bat               |  213 +

.../Ipmi/Library/IpmiLibKcs/IpmiLibKcs.inf    |   10 +-

.../IpmiPlatformHookLib.inf                   |    6 +-

.../Include/Guid/PchRcVariable.h              |    6 +

.../Include/Guid/SetupVariable.h              |   15 +-

.../Intel/PurleyOpenBoardPkg/OpenBoardPkg.dec |    1 +

.../Bus/Pci/PciBusDxe/ComponentName.c         |  170 +

.../Bus/Pci/PciBusDxe/ComponentName.h         |  146 +

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c   |  460 ++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h   |  396 ++

.../Bus/Pci/PciBusDxe/PciBusDxe.inf           |  112 +

.../Bus/Pci/PciBusDxe/PciBusDxe.uni           |   16 +

.../Bus/Pci/PciBusDxe/PciBusDxeExtra.uni      |   14 +

.../Bus/Pci/PciBusDxe/PciCommand.c            |  267 +

.../Bus/Pci/PciBusDxe/PciCommand.h            |  232 +

.../Bus/Pci/PciBusDxe/PciDeviceSupport.c      | 1056 +++

.../Bus/Pci/PciBusDxe/PciDeviceSupport.h      |  266 +

.../Bus/Pci/PciBusDxe/PciDriverOverride.c     |  188 +

.../Bus/Pci/PciBusDxe/PciDriverOverride.h     |   83 +

.../Bus/Pci/PciBusDxe/PciEnumerator.c         | 2210 ++++++

.../Bus/Pci/PciBusDxe/PciEnumerator.h         |  515 ++

.../Bus/Pci/PciBusDxe/PciEnumeratorSupport.c  | 2885 ++++++++  .../Bus/Pci/PciBusDxe/PciEnumeratorSupport.h  |  480 ++

.../Bus/Pci/PciBusDxe/PciHotPlugSupport.c     |  484 ++

.../Bus/Pci/PciBusDxe/PciHotPlugSupport.h     |  205 +

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c    | 2087 ++++++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h    |  660 ++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c   | 1809 +++++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h   |  179 +

.../Bus/Pci/PciBusDxe/PciOptionRomSupport.c   |  776 ++

.../Bus/Pci/PciBusDxe/PciOptionRomSupport.h   |  136 +

.../Bus/Pci/PciBusDxe/PciPowerManagement.c    |   82 +

.../Bus/Pci/PciBusDxe/PciPowerManagement.h    |   28 +

.../Bus/Pci/PciBusDxe/PciResourceSupport.c    | 2292 ++++++

.../Bus/Pci/PciBusDxe/PciResourceSupport.h    |  456 ++

.../Bus/Pci/PciBusDxe/PciRomTable.c           |  135 +

.../Bus/Pci/PciBusDxe/PciRomTable.h           |   48 +

Platform/Intel/build.cfg                      |    2 +

Platform/Intel/build_bios.py                  |    3 +-

80 files changed, 30278 insertions(+), 240 deletions(-)  create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreDxeInclude.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootInclude.fdf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/GitEdk2MinTiogaPass.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BasePlatformHookLib/BasePlatformHookLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BasePlatformHookLib/BasePlatformHookLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeBoardAcpiTableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeBoardAcpiTableLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeTiogaPassAcpiTableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmBoardAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmBoardAcpiEnableLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmSiliconAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmTiogaPassAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/AllLanesEparam.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/GpioTable.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/IioBifur.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPostMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPostMemLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPreMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPreMemLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassDetect.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitLib.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitPostMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitPreMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/UsbOC.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/PeiReportFvLib/PeiReportFvLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/PeiReportFvLib/PeiReportFvLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/OpenBoardPkg.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/OpenBoardPkg.fdf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgBuildOption.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgConfig.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgPcd.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/StructureConfig.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/__init__.py

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/bld.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/build_board.py

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/build_config.cfg

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/logo.txt

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/postbuild.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/prebuild.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.uni

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxeExtra.uni

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.h
-The information contained in this message may be confidential and proprietary to American Megatrends (AMI). This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited. Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.

-The information contained in this message may be confidential and proprietary to American Megatrends (AMI). This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited. Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.

[-- Attachment #2: Type: text/html, Size: 50005 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with
  2021-06-17 16:41       ` manickavasakam karpagavinayagam
@ 2021-06-18  6:11         ` Ni, Ray
  2021-06-18 18:34           ` manickavasakam karpagavinayagam
  0 siblings, 1 reply; 7+ messages in thread
From: Ni, Ray @ 2021-06-18  6:11 UTC (permalink / raw)
  To: devel@edk2.groups.io, KARPAGAVINAYAGAM, MANICKAVASAKAM,
	Kinney, Michael D, gaoliming
  Cc: DOPPALAPUDI, HARIKRISHNA


[-- Attachment #1.1: Type: text/plain, Size: 20363 bytes --]

To skip loading an option rom for certain devices, can you use IncompatiblePciDevice->CheckDevice()?
[Table  Description automatically generated]

For skipping enumerating a certain device, we could change PciBus to skip enumerating if gPciPlatformProtocol->PlatformPrepController() returns error status for that device. Do you think this solution is feasible to you?

Thanks,
Ray

From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of manickavasakam karpagavinayagam
Sent: Friday, June 18, 2021 12:41 AM
To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io; gaoliming <gaoliming@byosoft.com.cn>; Ni, Ray <ray.ni@intel.com>
Cc: DOPPALAPUDI, HARIKRISHNA <harikrishnad@ami.com>
Subject: Re: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with

Mike :

During PCI Bus enumeration, we need to skip SPI Controller (because of a silicon sighting) or else any SET variable asserts.
Also, need to skip a specific MLX card UEFI OPROM or else will see CPU exception.

We checked the PCIBUS driver code flow and there is no generic hooks to skip enumerating a device and to override the OPROM contents.

To avoid overriding the PCIBUS driver with platform instance, we can have PciBus Hooks at various places in PCIBUS driver to skip the device from enumeration, overriding the OPROM contents etc..

Ex : MdeModulePkg\Bus\Pci\PciBusDxe\PciLib.c PciScanBus()

        for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
    TempReservedBusNum = 0;
    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {

      //
      // Check to see whether a pci device is present
      //
      Status = PciDevicePresent (
                PciRootBridgeIo,
                &Pci,
                StartBusNumber,
                Device,
                Func
                );

      if (EFI_ERROR (Status) && Func == 0) {
        //
        // go to next device if there is no Function 0
        //
        break;
      }

      if (EFI_ERROR (Status)) {
        continue;
      }


      Status = PciOemPlatformHooks(&Pci, isPciSkipDevice, &Pci, &StartBusNumber, &Device, &Func);
      if(EFI_ERROR(Status))
      {
          if(Status==EFI_UNSUPPORTED){
              Status=EFI_SUCCESS;
          } else ASSERT_EFI_ERROR(Status);
      }
      else
      {
          DEBUG((DEBUG_INFO,"Device @ [B%X|D%X|F%X], VID=%X, DID=%X SKIPPED from enumeration.\n\n",
                  StartBusNumber, Device, Func,
                  Pci.Hdr.VendorId,Pci.Hdr.DeviceId));
          continue;
      }

      //
      // Get the PCI device information
      //
      Status = PciSearchDevice (
                Bridge,
                &Pci,
                StartBusNumber,
                Device,
                Func,
                &PciDevice
                );

      if (EFI_ERROR (Status)) {
        continue;
      }

Thank you

-Manic

From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Sent: Thursday, June 17, 2021 11:19 AM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Manickavasakam Karpagavinayagam <manickavasakamk@ami.com<mailto:manickavasakamk@ami.com>>; gaoliming <gaoliming@byosoft.com.cn<mailto:gaoliming@byosoft.com.cn>>; Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Cc: Harikrishna Doppalapudi <Harikrishnad@ami.com<mailto:Harikrishnad@ami.com>>
Subject: RE: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with

Has the reason for the PciBusDxe override been discussed with the PciBusDxe maintainer?

What feature would need to be added to PciBusDxe to accommodate the use case?

Mike

From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> On Behalf Of manickavasakam karpagavinayagam
Sent: Thursday, June 17, 2021 7:56 AM
To: gaoliming <gaoliming@byosoft.com.cn<mailto:gaoliming@byosoft.com.cn>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>
Cc: DOPPALAPUDI, HARIKRISHNA <harikrishnad@ami.com<mailto:harikrishnad@ami.com>>
Subject: Re: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with

Liming :

Below email is the cover letter and this patch series has two changes. Sure next time, will add more comments in the cover letter also.
Please refer the attached email and it has information about the PCIBUS override changes. PCIBUS override is done based on the platform sighting and it can’t be generic.

Thank you

-Manic

From: gaoliming <gaoliming@byosoft.com.cn<mailto:gaoliming@byosoft.com.cn>>
Sent: Wednesday, June 16, 2021 10:56 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Manickavasakam Karpagavinayagam <manickavasakamk@ami.com<mailto:manickavasakamk@ami.com>>
Subject: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with


**CAUTION: The e-mail below is from an external source. Please exercise caution before opening attachments, clicking links, or following guidance.**

Please follow https://github.com/tianocore/tianocore.github.io/wiki/Commit-Message-Format<https://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FCommit-Message-Format&data=04%7C01%7Cmanickavasakamk%40ami.com%7Cf76e7f29b16b4cf90ec908d931a340b2%7C27e97857e15f486cb58e86c2b3040f93%7C1%7C0%7C637595399503823678%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=w%2BRgvWwnXJy1wlN%2F%2Bbr9zvlp2etWRHhRRuiie7mViRA%3D&reserved=0> to update the commit message format.

And, for the override PciBus module, can you give more detail why need to override PciBus? Is it possible to update Edk2 MdeModulePkg PciBus to meet the platform requirement?

Thanks
Liming
发件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> 代表 manickavasakam karpagavinayagam
发送时间: 2021年6月17日 7:05
收件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
主题: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with


Add BoardTiogaPass packages to support TiogaPass Platform Enabled Network, ISCSI,IPMI, SMBIOS, Performance Measurement
Remove AST2500 UEFI option ROM driver from PurleyOpenBoardPkg

AST2500 UEFI option ROM move to edk2-non-osi ASpeedGopBinPkg Update copyright headers



manickavasakam karpagavinayagam (2):

  PurleyOpenBoardPkg : Support for TiogaPass Platform

  PurleyOpenBoardPkg : Override generic PciBus Driver with Platform

    specific instance of PciBus driver.



.../IpmiFeaturePkg/GenericIpmi/Dxe/IpmiInit.c |    8 +-

.../Acpi/BoardAcpiDxe/AmlOffsetTable.c        |  453 +-

.../Acpi/BoardAcpiDxe/BoardAcpiDxeDsdt.c      |    3 +

.../BoardTiogaPass/CoreDxeInclude.dsc         |  168 +

.../BoardTiogaPass/CoreUefiBootInclude.fdf    |   82 +

.../BoardTiogaPass/GitEdk2MinTiogaPass.bat    |   93 +

.../BasePlatformHookLib/BasePlatformHookLib.c |  389 +

.../BasePlatformHookLib.inf                   |   36 +

.../BoardAcpiLib/DxeBoardAcpiTableLib.c       |   36 +

.../BoardAcpiLib/DxeBoardAcpiTableLib.inf     |   40 +

.../BoardAcpiLib/DxeTiogaPassAcpiTableLib.c   |   53 +

.../BoardAcpiLib/SmmBoardAcpiEnableLib.c      |   62 +

.../BoardAcpiLib/SmmBoardAcpiEnableLib.inf    |   41 +

.../BoardAcpiLib/SmmSiliconAcpiEnableLib.c    |  120 +

.../BoardAcpiLib/SmmTiogaPassAcpiEnableLib.c  |   37 +

.../Library/BoardInitLib/AllLanesEparam.c     |   44 +

.../Library/BoardInitLib/GpioTable.c          |  296 +

.../Library/BoardInitLib/IioBifur.c           |   70 +

.../BoardInitLib/PeiBoardInitPostMemLib.c     |   46 +

.../BoardInitLib/PeiBoardInitPostMemLib.inf   |   37 +

.../BoardInitLib/PeiBoardInitPreMemLib.c      |  112 +

.../BoardInitLib/PeiBoardInitPreMemLib.inf    |   69 +

.../Library/BoardInitLib/PeiTiogaPassDetect.c |   28 +

.../BoardInitLib/PeiTiogaPassInitLib.h        |   18 +

.../BoardInitLib/PeiTiogaPassInitPostMemLib.c |   86 +

.../BoardInitLib/PeiTiogaPassInitPreMemLib.c  |  638 ++

.../Library/BoardInitLib/UsbOC.c              |   46 +

.../Library/PeiReportFvLib/PeiReportFvLib.c   |  138 +

.../Library/PeiReportFvLib/PeiReportFvLib.inf |   51 +

.../BoardTiogaPass/OpenBoardPkg.dsc           |  245 +

.../BoardTiogaPass/OpenBoardPkg.fdf           |  600 ++

.../BoardTiogaPass/PlatformPkgBuildOption.dsc |   84 +

.../BoardTiogaPass/PlatformPkgConfig.dsc      |   58 +

.../BoardTiogaPass/PlatformPkgPcd.dsc         |  392 ++

.../BoardTiogaPass/StructureConfig.dsc        | 6236 +++++++++++++++++

.../BoardTiogaPass/__init__.py                |    0

.../PurleyOpenBoardPkg/BoardTiogaPass/bld.bat |  139 +

.../BoardTiogaPass/build_board.py             |  195 +

.../BoardTiogaPass/build_config.cfg           |   34 +

.../BoardTiogaPass/logo.txt                   |   10 +

.../BoardTiogaPass/postbuild.bat              |   96 +

.../BoardTiogaPass/prebuild.bat               |  213 +

.../Ipmi/Library/IpmiLibKcs/IpmiLibKcs.inf    |   10 +-

.../IpmiPlatformHookLib.inf                   |    6 +-

.../Include/Guid/PchRcVariable.h              |    6 +

.../Include/Guid/SetupVariable.h              |   15 +-

.../Intel/PurleyOpenBoardPkg/OpenBoardPkg.dec |    1 +

.../Bus/Pci/PciBusDxe/ComponentName.c         |  170 +

.../Bus/Pci/PciBusDxe/ComponentName.h         |  146 +

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c   |  460 ++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h   |  396 ++

.../Bus/Pci/PciBusDxe/PciBusDxe.inf           |  112 +

.../Bus/Pci/PciBusDxe/PciBusDxe.uni           |   16 +

.../Bus/Pci/PciBusDxe/PciBusDxeExtra.uni      |   14 +

.../Bus/Pci/PciBusDxe/PciCommand.c            |  267 +

.../Bus/Pci/PciBusDxe/PciCommand.h            |  232 +

.../Bus/Pci/PciBusDxe/PciDeviceSupport.c      | 1056 +++

.../Bus/Pci/PciBusDxe/PciDeviceSupport.h      |  266 +

.../Bus/Pci/PciBusDxe/PciDriverOverride.c     |  188 +

.../Bus/Pci/PciBusDxe/PciDriverOverride.h     |   83 +

.../Bus/Pci/PciBusDxe/PciEnumerator.c         | 2210 ++++++

.../Bus/Pci/PciBusDxe/PciEnumerator.h         |  515 ++

.../Bus/Pci/PciBusDxe/PciEnumeratorSupport.c  | 2885 ++++++++  .../Bus/Pci/PciBusDxe/PciEnumeratorSupport.h  |  480 ++

.../Bus/Pci/PciBusDxe/PciHotPlugSupport.c     |  484 ++

.../Bus/Pci/PciBusDxe/PciHotPlugSupport.h     |  205 +

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c    | 2087 ++++++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h    |  660 ++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c   | 1809 +++++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h   |  179 +

.../Bus/Pci/PciBusDxe/PciOptionRomSupport.c   |  776 ++

.../Bus/Pci/PciBusDxe/PciOptionRomSupport.h   |  136 +

.../Bus/Pci/PciBusDxe/PciPowerManagement.c    |   82 +

.../Bus/Pci/PciBusDxe/PciPowerManagement.h    |   28 +

.../Bus/Pci/PciBusDxe/PciResourceSupport.c    | 2292 ++++++

.../Bus/Pci/PciBusDxe/PciResourceSupport.h    |  456 ++

.../Bus/Pci/PciBusDxe/PciRomTable.c           |  135 +

.../Bus/Pci/PciBusDxe/PciRomTable.h           |   48 +

Platform/Intel/build.cfg                      |    2 +

Platform/Intel/build_bios.py                  |    3 +-

80 files changed, 30278 insertions(+), 240 deletions(-)  create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreDxeInclude.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootInclude.fdf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/GitEdk2MinTiogaPass.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BasePlatformHookLib/BasePlatformHookLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BasePlatformHookLib/BasePlatformHookLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeBoardAcpiTableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeBoardAcpiTableLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeTiogaPassAcpiTableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmBoardAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmBoardAcpiEnableLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmSiliconAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmTiogaPassAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/AllLanesEparam.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/GpioTable.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/IioBifur.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPostMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPostMemLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPreMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPreMemLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassDetect.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitLib.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitPostMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitPreMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/UsbOC.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/PeiReportFvLib/PeiReportFvLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/PeiReportFvLib/PeiReportFvLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/OpenBoardPkg.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/OpenBoardPkg.fdf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgBuildOption.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgConfig.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgPcd.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/StructureConfig.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/__init__.py

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/bld.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/build_board.py

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/build_config.cfg

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/logo.txt

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/postbuild.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/prebuild.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.uni

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxeExtra.uni

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.h
-The information contained in this message may be confidential and proprietary to American Megatrends (AMI). This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited. Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.
-The information contained in this message may be confidential and proprietary to American Megatrends (AMI). This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited. Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.


[-- Attachment #1.2: Type: text/html, Size: 52900 bytes --]

[-- Attachment #2: image001.png --]
[-- Type: image/png, Size: 130146 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with
  2021-06-18  6:11         ` Ni, Ray
@ 2021-06-18 18:34           ` manickavasakam karpagavinayagam
  0 siblings, 0 replies; 7+ messages in thread
From: manickavasakam karpagavinayagam @ 2021-06-18 18:34 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io, Kinney, Michael D, gaoliming
  Cc: Harikrishna Doppalapudi


[-- Attachment #1.1: Type: text/plain, Size: 22383 bytes --]

Ray :

Regarding the OPROM skipping :

Current edk2\MdeModulePkg\Bus\Pci\PciBusDxe\PciEnumeratorSupport.c PciSearchDevice()->UpdatePciInfo() doesn’t consider Specific Type Flag to skip the device OPROM (do not probe option ROM Bar)
Also, in GetOpRomInfo() also doesn’t have a check to skip the device bar. Because of the current implementation, there is no other way other than overriding PCIBUS Driver.

Please correct me if the understanding is wrong.

Regarding the Device enumeration skipping :

As you said if modification done to return error status after PreprocessController () change will work for the devices that needs to be skipped after probing.
But if we want to skip the device before probing itself then edk2\MdeModulePkg\Bus\Pci\PciBusDxe\PciLib.c PreprocessController() won’t work.

Thank you

-Manic

From: Ni, Ray <ray.ni@intel.com>
Sent: Friday, June 18, 2021 2:11 AM
To: devel@edk2.groups.io; Manickavasakam Karpagavinayagam <manickavasakamk@ami.com>; Kinney, Michael D <michael.d.kinney@intel.com>; gaoliming <gaoliming@byosoft.com.cn>
Cc: Harikrishna Doppalapudi <Harikrishnad@ami.com>
Subject: RE: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with

To skip loading an option rom for certain devices, can you use IncompatiblePciDevice->CheckDevice()?
[Table  Description automatically generated]

For skipping enumerating a certain device, we could change PciBus to skip enumerating if gPciPlatformProtocol->PlatformPrepController() returns error status for that device. Do you think this solution is feasible to you?

Thanks,
Ray

From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> On Behalf Of manickavasakam karpagavinayagam
Sent: Friday, June 18, 2021 12:41 AM
To: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; gaoliming <gaoliming@byosoft.com.cn<mailto:gaoliming@byosoft.com.cn>>; Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>>
Cc: DOPPALAPUDI, HARIKRISHNA <harikrishnad@ami.com<mailto:harikrishnad@ami.com>>
Subject: Re: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with

Mike :

During PCI Bus enumeration, we need to skip SPI Controller (because of a silicon sighting) or else any SET variable asserts.
Also, need to skip a specific MLX card UEFI OPROM or else will see CPU exception.

We checked the PCIBUS driver code flow and there is no generic hooks to skip enumerating a device and to override the OPROM contents.

To avoid overriding the PCIBUS driver with platform instance, we can have PciBus Hooks at various places in PCIBUS driver to skip the device from enumeration, overriding the OPROM contents etc..

Ex : MdeModulePkg\Bus\Pci\PciBusDxe\PciLib.c PciScanBus()

        for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
    TempReservedBusNum = 0;
    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {

      //
      // Check to see whether a pci device is present
      //
      Status = PciDevicePresent (
                PciRootBridgeIo,
                &Pci,
                StartBusNumber,
                Device,
                Func
                );

      if (EFI_ERROR (Status) && Func == 0) {
        //
        // go to next device if there is no Function 0
        //
        break;
      }

      if (EFI_ERROR (Status)) {
        continue;
      }


      Status = PciOemPlatformHooks(&Pci, isPciSkipDevice, &Pci, &StartBusNumber, &Device, &Func);
      if(EFI_ERROR(Status))
      {
          if(Status==EFI_UNSUPPORTED){
              Status=EFI_SUCCESS;
          } else ASSERT_EFI_ERROR(Status);
      }
      else
      {
          DEBUG((DEBUG_INFO,"Device @ [B%X|D%X|F%X], VID=%X, DID=%X SKIPPED from enumeration.\n\n",
                  StartBusNumber, Device, Func,
                  Pci.Hdr.VendorId,Pci.Hdr.DeviceId));
          continue;
      }

      //
      // Get the PCI device information
      //
      Status = PciSearchDevice (
                Bridge,
                &Pci,
                StartBusNumber,
                Device,
                Func,
                &PciDevice
                );

      if (EFI_ERROR (Status)) {
        continue;
      }

Thank you

-Manic

From: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Sent: Thursday, June 17, 2021 11:19 AM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Manickavasakam Karpagavinayagam <manickavasakamk@ami.com<mailto:manickavasakamk@ami.com>>; gaoliming <gaoliming@byosoft.com.cn<mailto:gaoliming@byosoft.com.cn>>; Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
Cc: Harikrishna Doppalapudi <Harikrishnad@ami.com<mailto:Harikrishnad@ami.com>>
Subject: RE: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with

Has the reason for the PciBusDxe override been discussed with the PciBusDxe maintainer?

What feature would need to be added to PciBusDxe to accommodate the use case?

Mike

From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> On Behalf Of manickavasakam karpagavinayagam
Sent: Thursday, June 17, 2021 7:56 AM
To: gaoliming <gaoliming@byosoft.com.cn<mailto:gaoliming@byosoft.com.cn>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>
Cc: DOPPALAPUDI, HARIKRISHNA <harikrishnad@ami.com<mailto:harikrishnad@ami.com>>
Subject: Re: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with

Liming :

Below email is the cover letter and this patch series has two changes. Sure next time, will add more comments in the cover letter also.
Please refer the attached email and it has information about the PCIBUS override changes. PCIBUS override is done based on the platform sighting and it can’t be generic.

Thank you

-Manic

From: gaoliming <gaoliming@byosoft.com.cn<mailto:gaoliming@byosoft.com.cn>>
Sent: Wednesday, June 16, 2021 10:56 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Manickavasakam Karpagavinayagam <manickavasakamk@ami.com<mailto:manickavasakamk@ami.com>>
Subject: [EXTERNAL] 回复: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with


**CAUTION: The e-mail below is from an external source. Please exercise caution before opening attachments, clicking links, or following guidance.**

Please follow https://github.com/tianocore/tianocore.github.io/wiki/Commit-Message-Format<https://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FCommit-Message-Format&data=04%7C01%7Cmanickavasakamk%40ami.com%7C13e47eb498484dc5f6d008d9321fdf23%7C27e97857e15f486cb58e86c2b3040f93%7C1%7C0%7C637595934745723599%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=4FhI7sVGcqp0MSY144doP2BZ1PVrDNkEd1Q2SfAwNPs%3D&reserved=0> to update the commit message format.

And, for the override PciBus module, can you give more detail why need to override PciBus? Is it possible to update Edk2 MdeModulePkg PciBus to meet the platform requirement?

Thanks
Liming
发件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> 代表 manickavasakam karpagavinayagam
发送时间: 2021年6月17日 7:05
收件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
主题: [edk2-devel] [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with


Add BoardTiogaPass packages to support TiogaPass Platform Enabled Network, ISCSI,IPMI, SMBIOS, Performance Measurement
Remove AST2500 UEFI option ROM driver from PurleyOpenBoardPkg

AST2500 UEFI option ROM move to edk2-non-osi ASpeedGopBinPkg Update copyright headers



manickavasakam karpagavinayagam (2):

  PurleyOpenBoardPkg : Support for TiogaPass Platform

  PurleyOpenBoardPkg : Override generic PciBus Driver with Platform

    specific instance of PciBus driver.



.../IpmiFeaturePkg/GenericIpmi/Dxe/IpmiInit.c |    8 +-

.../Acpi/BoardAcpiDxe/AmlOffsetTable.c        |  453 +-

.../Acpi/BoardAcpiDxe/BoardAcpiDxeDsdt.c      |    3 +

.../BoardTiogaPass/CoreDxeInclude.dsc         |  168 +

.../BoardTiogaPass/CoreUefiBootInclude.fdf    |   82 +

.../BoardTiogaPass/GitEdk2MinTiogaPass.bat    |   93 +

.../BasePlatformHookLib/BasePlatformHookLib.c |  389 +

.../BasePlatformHookLib.inf                   |   36 +

.../BoardAcpiLib/DxeBoardAcpiTableLib.c       |   36 +

.../BoardAcpiLib/DxeBoardAcpiTableLib.inf     |   40 +

.../BoardAcpiLib/DxeTiogaPassAcpiTableLib.c   |   53 +

.../BoardAcpiLib/SmmBoardAcpiEnableLib.c      |   62 +

.../BoardAcpiLib/SmmBoardAcpiEnableLib.inf    |   41 +

.../BoardAcpiLib/SmmSiliconAcpiEnableLib.c    |  120 +

.../BoardAcpiLib/SmmTiogaPassAcpiEnableLib.c  |   37 +

.../Library/BoardInitLib/AllLanesEparam.c     |   44 +

.../Library/BoardInitLib/GpioTable.c          |  296 +

.../Library/BoardInitLib/IioBifur.c           |   70 +

.../BoardInitLib/PeiBoardInitPostMemLib.c     |   46 +

.../BoardInitLib/PeiBoardInitPostMemLib.inf   |   37 +

.../BoardInitLib/PeiBoardInitPreMemLib.c      |  112 +

.../BoardInitLib/PeiBoardInitPreMemLib.inf    |   69 +

.../Library/BoardInitLib/PeiTiogaPassDetect.c |   28 +

.../BoardInitLib/PeiTiogaPassInitLib.h        |   18 +

.../BoardInitLib/PeiTiogaPassInitPostMemLib.c |   86 +

.../BoardInitLib/PeiTiogaPassInitPreMemLib.c  |  638 ++

.../Library/BoardInitLib/UsbOC.c              |   46 +

.../Library/PeiReportFvLib/PeiReportFvLib.c   |  138 +

.../Library/PeiReportFvLib/PeiReportFvLib.inf |   51 +

.../BoardTiogaPass/OpenBoardPkg.dsc           |  245 +

.../BoardTiogaPass/OpenBoardPkg.fdf           |  600 ++

.../BoardTiogaPass/PlatformPkgBuildOption.dsc |   84 +

.../BoardTiogaPass/PlatformPkgConfig.dsc      |   58 +

.../BoardTiogaPass/PlatformPkgPcd.dsc         |  392 ++

.../BoardTiogaPass/StructureConfig.dsc        | 6236 +++++++++++++++++

.../BoardTiogaPass/__init__.py                |    0

.../PurleyOpenBoardPkg/BoardTiogaPass/bld.bat |  139 +

.../BoardTiogaPass/build_board.py             |  195 +

.../BoardTiogaPass/build_config.cfg           |   34 +

.../BoardTiogaPass/logo.txt                   |   10 +

.../BoardTiogaPass/postbuild.bat              |   96 +

.../BoardTiogaPass/prebuild.bat               |  213 +

.../Ipmi/Library/IpmiLibKcs/IpmiLibKcs.inf    |   10 +-

.../IpmiPlatformHookLib.inf                   |    6 +-

.../Include/Guid/PchRcVariable.h              |    6 +

.../Include/Guid/SetupVariable.h              |   15 +-

.../Intel/PurleyOpenBoardPkg/OpenBoardPkg.dec |    1 +

.../Bus/Pci/PciBusDxe/ComponentName.c         |  170 +

.../Bus/Pci/PciBusDxe/ComponentName.h         |  146 +

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c   |  460 ++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h   |  396 ++

.../Bus/Pci/PciBusDxe/PciBusDxe.inf           |  112 +

.../Bus/Pci/PciBusDxe/PciBusDxe.uni           |   16 +

.../Bus/Pci/PciBusDxe/PciBusDxeExtra.uni      |   14 +

.../Bus/Pci/PciBusDxe/PciCommand.c            |  267 +

.../Bus/Pci/PciBusDxe/PciCommand.h            |  232 +

.../Bus/Pci/PciBusDxe/PciDeviceSupport.c      | 1056 +++

.../Bus/Pci/PciBusDxe/PciDeviceSupport.h      |  266 +

.../Bus/Pci/PciBusDxe/PciDriverOverride.c     |  188 +

.../Bus/Pci/PciBusDxe/PciDriverOverride.h     |   83 +

.../Bus/Pci/PciBusDxe/PciEnumerator.c         | 2210 ++++++

.../Bus/Pci/PciBusDxe/PciEnumerator.h         |  515 ++

.../Bus/Pci/PciBusDxe/PciEnumeratorSupport.c  | 2885 ++++++++  .../Bus/Pci/PciBusDxe/PciEnumeratorSupport.h  |  480 ++

.../Bus/Pci/PciBusDxe/PciHotPlugSupport.c     |  484 ++

.../Bus/Pci/PciBusDxe/PciHotPlugSupport.h     |  205 +

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c    | 2087 ++++++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h    |  660 ++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c   | 1809 +++++

.../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h   |  179 +

.../Bus/Pci/PciBusDxe/PciOptionRomSupport.c   |  776 ++

.../Bus/Pci/PciBusDxe/PciOptionRomSupport.h   |  136 +

.../Bus/Pci/PciBusDxe/PciPowerManagement.c    |   82 +

.../Bus/Pci/PciBusDxe/PciPowerManagement.h    |   28 +

.../Bus/Pci/PciBusDxe/PciResourceSupport.c    | 2292 ++++++

.../Bus/Pci/PciBusDxe/PciResourceSupport.h    |  456 ++

.../Bus/Pci/PciBusDxe/PciRomTable.c           |  135 +

.../Bus/Pci/PciBusDxe/PciRomTable.h           |   48 +

Platform/Intel/build.cfg                      |    2 +

Platform/Intel/build_bios.py                  |    3 +-

80 files changed, 30278 insertions(+), 240 deletions(-)  create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreDxeInclude.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootInclude.fdf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/GitEdk2MinTiogaPass.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BasePlatformHookLib/BasePlatformHookLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BasePlatformHookLib/BasePlatformHookLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeBoardAcpiTableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeBoardAcpiTableLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/DxeTiogaPassAcpiTableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmBoardAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmBoardAcpiEnableLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmSiliconAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardAcpiLib/SmmTiogaPassAcpiEnableLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/AllLanesEparam.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/GpioTable.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/IioBifur.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPostMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPostMemLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPreMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiBoardInitPreMemLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassDetect.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitLib.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitPostMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/PeiTiogaPassInitPreMemLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/BoardInitLib/UsbOC.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/PeiReportFvLib/PeiReportFvLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/Library/PeiReportFvLib/PeiReportFvLib.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/OpenBoardPkg.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/OpenBoardPkg.fdf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgBuildOption.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgConfig.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/PlatformPkgPcd.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/StructureConfig.dsc

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/__init__.py

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/bld.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/build_board.py

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/build_config.cfg

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/logo.txt

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/postbuild.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/prebuild.bat

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.uni

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxeExtra.uni

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.c

create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.h
-The information contained in this message may be confidential and proprietary to American Megatrends (AMI). This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited. Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.
-The information contained in this message may be confidential and proprietary to American Megatrends (AMI). This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited. Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.

-The information contained in this message may be confidential and proprietary to American Megatrends (AMI). This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited. Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.

[-- Attachment #1.2: Type: text/html, Size: 58379 bytes --]

[-- Attachment #2: image001.png --]
[-- Type: image/png, Size: 130146 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-06-18 18:34 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-06-16 23:04 [edk2-platforms] [PATCH V1 0/2] Support for TiogaPass Platform and Override generic PciBus Driver with manickavasakam karpagavinayagam
2021-06-17  2:56 ` 回复: [edk2-devel] " gaoliming
2021-06-17 14:55   ` [EXTERNAL] " manickavasakam karpagavinayagam
2021-06-17 15:19     ` Michael D Kinney
2021-06-17 16:41       ` manickavasakam karpagavinayagam
2021-06-18  6:11         ` Ni, Ray
2021-06-18 18:34           ` manickavasakam karpagavinayagam

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox