Discussion:
[edk2] [PATCH v3 00/23] OvmfPkg: support extra PCI root buses
Laszlo Ersek
2015-07-07 15:09:02 UTC
Permalink
Changes in v3 (also noted per patch):

- The PciHostBridgeDxe driver is now rewrapped to 79 columns in its
original place, under PcAtChipsetPkg. No other (ie. no functional)
changes are made to PcAtChipsetPkg/PciHostBridgeDxe. The clone under
OvmfPkg is created from the rewrapped source code.

- The very last patch has been updated to the most recently agreed upon
OFW notation for extra root buses.

Public branch:
https://github.com/lersek/edk2/commits/multiple_root_bridges_bz1193080_v3

Cc: Jordan Justen <***@intel.com>
Cc: Ruiyu Ni <***@intel.com>
Cc: Gabriel Somlo <***@cmu.edu>

Laszlo Ersek (23):
PcAtChipsetPkg: PciHostBridgeDxe: rewrap IoFifo source files to 79
columns
PcAtChipsetPkg: PciHostBridgeDxe: rewrap INF file to 79 columns
PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.h: rewrap comments to 79
columns
PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.h: strip trailing ws
from code
PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.c: rewrap leading
comments
PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.c: rewrap code, strip
trailing ws
PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c: rewrap leading
comments
PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c: rewrap code, strip
trailing ws
OvmfPkg: clone PciHostBridgeDxe from PcAtChipsetPkg
OvmfPkg: PlatformBdsLib: debug log interrupt line assignments
OvmfPkg: PlatformBdsLib: refine PCI host bridge assertion
OvmfPkg: PlatformBdsLib: connect all PCI root buses
OvmfPkg: PciHostBridgeDxe: eliminate nominal support for multiple host
bridges
OvmfPkg: PciHostBridgeDxe: kill RootBridgeNumber and
RootBridgeAttribute
OvmfPkg: PciHostBridgeDxe: embed device path in private root bridge
struct
OvmfPkg: PciHostBridgeDxe: factor out InitRootBridge() function
OvmfPkg: PciHostBridgeDxe: release resources on driver entry failure
OvmfPkg: PciHostBridgeDxe: use private buffer in
RootBridgeIoConfiguration()
OvmfPkg: PciHostBridgeDxe: eliminate
PCI_HOST_BRIDGE_INSTANCE.RootBridgeNumber
OvmfPkg: PciHostBridgeDxe: look for all root buses
OvmfPkg: PciHostBridgeDxe: shorten search for extra root buses
OvmfPkg: QemuBootOrderLib: introduce ExtraRootBusMap
OvmfPkg: QemuBootOrderLib: recognize extra PCI root buses

OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c | 88 +-
OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h | 25 +-
OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf | 2 +-
OvmfPkg/Library/PlatformBdsLib/PlatformData.c | 13 -
OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.c | 313 +++
OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.h | 40 +
OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c | 152 +-
OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf | 6 +
OvmfPkg/OvmfPkgIa32.dsc | 2 +-
OvmfPkg/OvmfPkgIa32.fdf | 2 +-
OvmfPkg/OvmfPkgIa32X64.dsc | 2 +-
OvmfPkg/OvmfPkgIa32X64.fdf | 2 +-
OvmfPkg/OvmfPkgX64.dsc | 2 +-
OvmfPkg/OvmfPkgX64.fdf | 2 +-
OvmfPkg/PciHostBridgeDxe/PciHostBridge.c | 1551 ++++++++++++
OvmfPkg/PciHostBridgeDxe/PciHostBridge.h | 651 +++++
OvmfPkg/PciHostBridgeDxe/PciRootBridgeIo.c | 2628 ++++++++++++++++++++
PcAtChipsetPkg/PciHostBridgeDxe/Ia32/IoFifo.S | 7 +-
PcAtChipsetPkg/PciHostBridgeDxe/Ia32/IoFifo.asm | 7 +-
PcAtChipsetPkg/PciHostBridgeDxe/IoFifo.h | 11 +-
PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.c | 976 +++++---
PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.h | 624 +++--
PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf | 13 +-
PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c | 2054 +++++++++------
PcAtChipsetPkg/PciHostBridgeDxe/X64/IoFifo.S | 7 +-
PcAtChipsetPkg/PciHostBridgeDxe/X64/IoFifo.asm | 7 +-
{PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/Ia32/IoFifo.S | 7 +-
{PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/Ia32/IoFifo.asm | 7 +-
{PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/IoFifo.h | 11 +-
{PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/PciHostBridgeDxe.inf | 21 +-
{PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/X64/IoFifo.S | 7 +-
{PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/X64/IoFifo.asm | 7 +-
32 files changed, 7669 insertions(+), 1578 deletions(-)
copy {PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/Ia32/IoFifo.S (90%)
copy {PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/Ia32/IoFifo.asm (90%)
copy {PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/IoFifo.h (91%)
copy {PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/PciHostBridgeDxe.inf (72%)
copy {PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/X64/IoFifo.S (92%)
copy {PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/X64/IoFifo.asm (91%)
create mode 100644 OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.c
create mode 100644 OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.h
create mode 100644 OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
create mode 100644 OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
create mode 100644 OvmfPkg/PciHostBridgeDxe/PciRootBridgeIo.c
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:04 UTC
Permalink
Cc: Ruiyu Ni <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
Reviewed-by: Ruiyu Ni <***@intel.com>
---

Notes:
v3:
- rewrap the driver under PcAtChipsetPkg

PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf b/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
index 613c29f..be3622b 100644
--- a/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
+++ b/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
@@ -1,14 +1,17 @@
## @file
-# The basic interfaces implementation to a single segment PCI Host Bridge driver.
+# The basic interfaces implementation to a single segment PCI Host Bridge
+# driver.
#
# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
-# This program and the accompanying materials
-# are licensed and made available under the terms and conditions of the BSD License
-# which accompanies this distribution. The full text of the license may be found at
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License which accompanies this
+# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED.
#
##
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:06 UTC
Permalink
Cc: Ruiyu Ni <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
Reviewed-by: Ruiyu Ni <***@intel.com>
---

Notes:
v3:
- rewrap the driver under PcAtChipsetPkg

PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.h | 34 ++++++++++----------
1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.h b/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.h
index 59f47e7..f475eb7 100644
--- a/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.h
+++ b/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.h
@@ -59,14 +59,14 @@ typedef struct {
EFI_HANDLE HostBridgeHandle;
UINTN RootBridgeNumber;
LIST_ENTRY Head;
- BOOLEAN ResourceSubmited;
- BOOLEAN CanRestarted;
+ BOOLEAN ResourceSubmited;
+ BOOLEAN CanRestarted;
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL ResAlloc;
} PCI_HOST_BRIDGE_INSTANCE;

#define INSTANCE_FROM_RESOURCE_ALLOCATION_THIS(a) \
CR(a, PCI_HOST_BRIDGE_INSTANCE, ResAlloc, PCI_HOST_BRIDGE_SIGNATURE)
-
+
//
// HostBridge Resource Allocation interface
//
@@ -551,13 +551,13 @@ typedef struct {

typedef struct {
UINT64 BusBase;
- UINT64 BusLimit;
-
- UINT64 MemBase;
- UINT64 MemLimit;
-
- UINT64 IoBase;
- UINT64 IoLimit;
+ UINT64 BusLimit;
+
+ UINT64 MemBase;
+ UINT64 MemLimit;
+
+ UINT64 IoBase;
+ UINT64 IoLimit;
} PCI_ROOT_BRIDGE_RESOURCE_APERTURE;

typedef enum {
@@ -595,21 +595,21 @@ typedef struct {
UINT64 RootBridgeAttrib;
UINT64 Attributes;
UINT64 Supports;
-
+
//
// Specific for this memory controller: Bus, I/O, Mem
//
PCI_RES_NODE ResAllocNode[6];
-
+
//
// Addressing for Memory and I/O and Bus arrange
//
UINT64 BusBase;
- UINT64 MemBase;
- UINT64 IoBase;
- UINT64 BusLimit;
- UINT64 MemLimit;
- UINT64 IoLimit;
+ UINT64 MemBase;
+ UINT64 IoBase;
+ UINT64 BusLimit;
+ UINT64 MemLimit;
+ UINT64 IoLimit;

EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:05 UTC
Permalink
Cc: Ruiyu Ni <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
Reviewed-by: Ruiyu Ni <***@intel.com>
---

Notes:
v3:
- rewrap the driver under PcAtChipsetPkg

PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.h | 590 ++++++++++++--------
1 file changed, 372 insertions(+), 218 deletions(-)

diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.h b/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.h
index f9ef7d8..59f47e7 100644
--- a/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.h
+++ b/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.h
@@ -1,16 +1,16 @@
/** @file
- The Header file of the Pci Host Bridge Driver
+ The Header file of the Pci Host Bridge Driver

Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
- This program and the accompanying materials are
- licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
-
+
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
+**/

#ifndef _PCI_HOST_BRIDGE_H_
#define _PCI_HOST_BRIDGE_H_
@@ -72,68 +72,114 @@ typedef struct {
//

/**
- 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] This 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.
+ 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] This 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
EFIAPI
@@ -143,26 +189,38 @@ NotifyPhase(
);

/**
- Return the device handle of the next PCI root bridge that is associated with this Host Bridge.
+ Return the device handle of the next PCI root bridge that is associated with
+ this Host Bridge.

- This function is called multiple times to retrieve the device handles of all the PCI root bridges that
- are associated with this PCI host bridge. Each PCI host bridge is associated with one or more PCI
- root bridges. On each call, the handle that was returned by the previous call is passed into the
- interface, and on output the interface returns the device handle of the next PCI root bridge. The
- caller can use the handle to obtain the instance of the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
- for that root bridge. When there are no more PCI root bridges to report, the interface returns
- EFI_NOT_FOUND. A PCI enumerator must enumerate the PCI root bridges in the order that they
- are returned by this function.
- For D945 implementation, there is only one root bridge in PCI host bridge.
+ This function is called multiple times to retrieve the device handles of all
+ the PCI root bridges that are associated with this PCI host bridge. Each PCI
+ host bridge is associated with one or more PCI root bridges. On each call,
+ the handle that was returned by the previous call is passed into the
+ interface, and on output the interface returns the device handle of the next
+ PCI root bridge. The caller can use the handle to obtain the instance of the
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL for that root bridge. When there are no more
+ PCI root bridges to report, the interface returns EFI_NOT_FOUND. A PCI
+ enumerator must enumerate the PCI root bridges in the order that they are
+ returned by this function.

- @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
- @param[in, out] RootBridgeHandle Returns the device handle of the next PCI root bridge.
-
- @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then return the first Rootbridge handle of the
- specific Host bridge and return EFI_SUCCESS.
- @retval EFI_NOT_FOUND Can not find the any more root bridge in specific host bridge.
- @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was
- returned on a previous call to GetNextRootBridge().
+ For D945 implementation, there is only one root bridge in PCI host bridge.
+
+ @param[in] This The instance pointer of
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+
+ @param[in, out] RootBridgeHandle Returns the device handle of the next PCI
+ root bridge.
+
+ @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then
+ return the first Rootbridge handle of the
+ specific Host bridge and return EFI_SUCCESS.
+
+ @retval EFI_NOT_FOUND Can not find the any more root bridge in
+ specific host bridge.
+
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was
+ returned on a previous call to
+ GetNextRootBridge().
**/
EFI_STATUS
EFIAPI
@@ -170,45 +228,65 @@ GetNextRootBridge(
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
IN OUT EFI_HANDLE *RootBridgeHandle
);
-
+
/**
- Returns the allocation attributes of a PCI root bridge.
-
- The function returns the allocation attributes of a specific PCI root bridge. The attributes can vary
- from one PCI root bridge to another. These attributes are different from the decode-related
- attributes that are returned by the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
- RootBridgeHandle parameter is used to specify the instance of the PCI root bridge. The device
- handles of all the root bridges that are associated with this host bridge must be obtained by calling
- GetNextRootBridge(). The attributes are static in the sense that they do not change during or
- after the enumeration process. The hardware may provide mechanisms to change the attributes on
- the fly, but such changes must be completed before EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is
- installed. The permitted values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
- "Related Definitions" below. The caller uses these attributes to combine multiple resource requests.
- For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI bus enumerator needs to
- include requests for the prefetchable memory in the nonprefetchable memory pool and not request any
- prefetchable memory.
- Attribute Description
- ------------------------------------ ----------------------------------------------------------------------
- EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root bridge does not support separate
- windows for nonprefetchable and prefetchable memory. A PCI bus
- driver needs to include requests for prefetchable memory in the
- nonprefetchable memory pool.
-
- EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root bridge supports 64-bit memory
- windows. If this bit is not set, the PCI bus driver needs to include
- requests for a 64-bit memory address in the corresponding 32-bit
- memory pool.
-
- @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
- @param[in] RootBridgeHandle The device handle of the PCI root bridge in which the caller is interested. Type
- EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
- @param[out] Attributes The pointer to attribte of root bridge, it is output parameter
-
- @retval EFI_INVALID_PARAMETER Attribute pointer is NULL
- @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid.
- @retval EFI_SUCCESS Success to get attribute of interested root bridge.
-
-**/
+ Returns the allocation attributes of a PCI root bridge.
+
+ The function returns the allocation attributes of a specific PCI root bridge.
+ The attributes can vary from one PCI root bridge to another. These attributes
+ are different from the decode-related attributes that are returned by the
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
+ RootBridgeHandle parameter is used to specify the instance of the PCI root
+ bridge. The device handles of all the root bridges that are associated with
+ this host bridge must be obtained by calling GetNextRootBridge(). The
+ attributes are static in the sense that they do not change during or after
+ the enumeration process. The hardware may provide mechanisms to change the
+ attributes on the fly, but such changes must be completed before
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is installed. The permitted
+ values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
+ "Related Definitions" below. The caller uses these attributes to combine
+ multiple resource requests.
+
+ For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI
+ bus enumerator needs to include requests for the prefetchable memory in the
+ nonprefetchable memory pool and not request any prefetchable memory.
+
+ Attribute Description
+ ------------------------------------ ---------------------------------------
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root
+ bridge does not support separate
+ windows for nonprefetchable and
+ prefetchable memory. A PCI bus driver
+ needs to include requests for
+ prefetchable memory in the
+ nonprefetchable memory pool.
+
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root
+ bridge supports 64-bit memory windows.
+ If this bit is not set, the PCI bus
+ driver needs to include requests for a
+ 64-bit memory address in the
+ corresponding 32-bit memory pool.
+
+ @param[in] This The instance pointer of
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+
+ @param[in] RootBridgeHandle The device handle of the PCI root bridge in
+ which the caller is interested. Type
+ EFI_HANDLE is defined in
+ InstallProtocolInterface() in the UEFI 2.0
+ Specification.
+
+ @param[out] Attributes The pointer to attribte of root bridge, it is
+ output parameter
+
+ @retval EFI_INVALID_PARAMETER Attribute pointer is NULL
+
+ @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid.
+
+ @retval EFI_SUCCESS Success to get attribute of interested root
+ bridge.
+**/
EFI_STATUS
EFIAPI
GetAttributes(
@@ -216,21 +294,28 @@ GetAttributes(
IN EFI_HANDLE RootBridgeHandle,
OUT UINT64 *Attributes
);
-
+
/**
- Sets up the specified PCI root bridge for the bus enumeration process.
+ Sets up the specified PCI root bridge for the bus enumeration process.

- This member function sets up the root bridge for bus enumeration and returns the PCI bus range
- over which the search should be performed in ACPI 2.0 resource descriptor format.
+ This member function sets up the root bridge for bus enumeration and returns
+ the PCI bus range over which the search should be performed in ACPI 2.0
+ resource descriptor format.

- @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
- @param[in] RootBridgeHandle The PCI Root Bridge to be set up.
- @param[out] Configuration Pointer to the pointer to the PCI bus resource descriptor.
-
- @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
- @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag.
- @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor.
+ @param[in] This The
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ instance.

+ @param[in] RootBridgeHandle The PCI Root Bridge to be set up.
+
+ @param[out] Configuration Pointer to the pointer to the PCI bus resource
+ descriptor.
+
+ @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
+
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag.
+
+ @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor.
**/
EFI_STATUS
EFIAPI
@@ -239,30 +324,52 @@ StartBusEnumeration(
IN EFI_HANDLE RootBridgeHandle,
OUT VOID **Configuration
);
-
+
/**
- Programs the PCI root bridge hardware so that it decodes the specified PCI bus range.
-
- This member function programs the specified PCI root bridge to decode the bus range that is
- specified by the input parameter Configuration.
- The bus range information is specified in terms of the ACPI 2.0 resource descriptor format.
-
- @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
- @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed
- @param[in] Configuration The pointer to the PCI bus resource descriptor
-
- @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
- @retval EFI_INVALID_PARAMETER Configuration is NULL.
- @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.
- @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI 2.0 bus resource descriptor.
- @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource descriptors other than
- bus descriptors.
- @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid ACPI resource descriptors.
- @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this root bridge.
- @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this root bridge.
- @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
- @retval EFI_SUCCESS The bus range for the PCI root bridge was programmed.
+ Programs the PCI root bridge hardware so that it decodes the specified PCI
+ bus range.

+ This member function programs the specified PCI root bridge to decode the bus
+ range that is specified by the input parameter Configuration.
+ The bus range information is specified in terms of the ACPI 2.0 resource
+ descriptor format.
+
+ @param[in] This The
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ instance
+
+ @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be
+ programmed
+
+ @param[in] Configuration The pointer to the PCI bus resource descriptor
+
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
+ handle.
+
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+
+ @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI
+ 2.0 resource descriptor.
+
+ @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI
+ 2.0 bus resource descriptor.
+
+ @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource
+ descriptors other than bus descriptors.
+
+ @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid
+ ACPI resource descriptors.
+
+ @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this
+ root bridge.
+
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
+
+ @retval EFI_SUCCESS The bus range for the PCI root bridge was
+ programmed.
**/
EFI_STATUS
EFIAPI
@@ -271,31 +378,52 @@ SetBusNumbers(
IN EFI_HANDLE RootBridgeHandle,
IN VOID *Configuration
);
-
+
/**
- Submits the I/O and memory resource requirements for the specified PCI root bridge.
-
- This function is used to submit all the I/O and memory resources that are required by the specified
- PCI root bridge. The input parameter Configuration is used to specify the following:
- - The various types of resources that are required
- - The associated lengths in terms of ACPI 2.0 resource descriptor format
-
- @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
- @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory resource requirements are being submitted.
- @param[in] Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
-
- @retval EFI_SUCCESS The I/O and memory resource requests for a PCI root bridge were accepted.
- @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
- @retval EFI_INVALID_PARAMETER Configuration is NULL.
- @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.
- @retval EFI_INVALID_PARAMETER Configuration includes requests for one or more resource types that are
- not supported by this PCI root bridge. This error will happen if the caller
- did not combine resources according to Attributes that were returned by
- GetAllocAttributes().
- @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid.
- @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI root bridge.
- @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for this PCI root bridge.
+ Submits the I/O and memory resource requirements for the specified PCI root
+ bridge.

+ This function is used to submit all the I/O and memory resources that are
+ required by the specified PCI root bridge. The input parameter Configuration
+ is used to specify the following:
+ - The various types of resources that are required
+ - The associated lengths in terms of ACPI 2.0 resource descriptor format
+
+ @param[in] This Pointer to the
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ instance.
+
+ @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory
+ resource requirements are being submitted.
+
+ @param[in] Configuration The pointer to the PCI I/O and PCI memory
+ resource descriptor.
+
+ @retval EFI_SUCCESS The I/O and memory resource requests for a PCI
+ root bridge were accepted.
+
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
+ handle.
+
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+
+ @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI
+ 2.0 resource descriptor.
+
+ @retval EFI_INVALID_PARAMETER Configuration includes requests for one or
+ more resource types that are not supported by
+ this PCI root bridge. This error will happen
+ if the caller did not combine resources
+ according to Attributes that were returned by
+ GetAllocAttributes().
+
+ @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid.
+
+ @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for
+ this PCI root bridge.
**/
EFI_STATUS
EFIAPI
@@ -304,26 +432,38 @@ SubmitResources(
IN EFI_HANDLE RootBridgeHandle,
IN VOID *Configuration
);
-
+
/**
Returns the proposed resource settings for the specified PCI root bridge.

- This member function returns the proposed resource settings for the specified PCI root bridge. The
- proposed resource settings are prepared when NotifyPhase() is called with a Phase of
- EfiPciHostBridgeAllocateResources. The output parameter Configuration
- specifies the following:
- - The various types of resources, excluding bus resources, that are allocated
+ This member function returns the proposed resource settings for the
+ specified PCI root bridge. The proposed resource settings are prepared when
+ NotifyPhase() is called with a Phase of EfiPciHostBridgeAllocateResources.
+ The output parameter Configuration specifies the following:
+ - The various types of resources, excluding bus resources, that are
+ allocated
- The associated lengths in terms of ACPI 2.0 resource descriptor format

- @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
- @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
- @param[out] Configuration The pointer to the pointer to the PCI I/O and memory resource descriptor.
-
+ @param[in] This Pointer to the
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ instance.
+
+ @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is
+ defined in InstallProtocolInterface() in the
+ UEFI 2.0 Specification.
+
+ @param[out] Configuration The pointer to the pointer to the PCI I/O and
+ memory resource descriptor.
+
@retval EFI_SUCCESS The requested parameters were returned.
- @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
+ handle.
+
@retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.

+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -334,31 +474,46 @@ GetProposedResources(
);

/**
- 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 This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
- @param RootBridgeHandle The associated PCI root bridge handle. Type EFI_HANDLE is defined in
- InstallProtocolInterface() in the UEFI 2.0 Specification.
- @param PciAddress The address of the PCI device on the PCI bus. This address can be passed to the
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to access the PCI
- configuration space of the device. See Table 12-1 in the UEFI 2.0 Specification for
- the definition of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
- @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.
+ 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 This Pointer to the
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ instance.
+
+ @param RootBridgeHandle The associated PCI root bridge handle. Type
+ EFI_HANDLE is defined in InstallProtocolInterface()
+ in the UEFI 2.0 Specification.
+
+ @param PciAddress The address of the PCI device on the PCI bus. This
+ address can be passed to the
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to
+ access the PCI configuration space of the device.
+ See Table 12-1 in the UEFI 2.0 Specification for the
+ definition of
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
+
+ @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
EFIAPI
@@ -371,7 +526,7 @@ PreprocessController (


//
-// Define resource status constant
+// Define resource status constant
//
#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL
#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL
@@ -482,7 +637,6 @@ typedef struct {
@param ResAperture ResourceAperture for host bridge

@retval EFI_SUCCESS Success to initialize the Pci Root Bridge.
-
**/
EFI_STATUS
RootBridgeConstructor (
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:03 UTC
Permalink
Cc: Ruiyu Ni <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
Reviewed-by: Ruiyu Ni <***@intel.com>
---

Notes:
v3:
- rewrap the driver under PcAtChipsetPkg

PcAtChipsetPkg/PciHostBridgeDxe/IoFifo.h | 11 ++++++-----
PcAtChipsetPkg/PciHostBridgeDxe/Ia32/IoFifo.S | 7 ++++---
PcAtChipsetPkg/PciHostBridgeDxe/Ia32/IoFifo.asm | 7 ++++---
PcAtChipsetPkg/PciHostBridgeDxe/X64/IoFifo.S | 7 ++++---
PcAtChipsetPkg/PciHostBridgeDxe/X64/IoFifo.asm | 7 ++++---
5 files changed, 22 insertions(+), 17 deletions(-)

diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/IoFifo.h b/PcAtChipsetPkg/PciHostBridgeDxe/IoFifo.h
index 5d48bf5..9978f8b 100644
--- a/PcAtChipsetPkg/PciHostBridgeDxe/IoFifo.h
+++ b/PcAtChipsetPkg/PciHostBridgeDxe/IoFifo.h
@@ -2,15 +2,16 @@
I/O FIFO routines

Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
- This program and the accompanying materials are
- licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
-
+
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

-**/
+**/

#ifndef _IO_FIFO_H_INCLUDED_
#define _IO_FIFO_H_INCLUDED_
diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/Ia32/IoFifo.S b/PcAtChipsetPkg/PciHostBridgeDxe/Ia32/IoFifo.S
index 6b9c096..03a014d 100644
--- a/PcAtChipsetPkg/PciHostBridgeDxe/Ia32/IoFifo.S
+++ b/PcAtChipsetPkg/PciHostBridgeDxe/Ia32/IoFifo.S
@@ -1,9 +1,10 @@
#------------------------------------------------------------------------------
#
# Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
-# This program and the accompanying materials
-# are licensed and made available under the terms and conditions of the BSD License
-# which accompanies this distribution. The full text of the license may be found at
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License which accompanies this
+# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php.
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/Ia32/IoFifo.asm b/PcAtChipsetPkg/PciHostBridgeDxe/Ia32/IoFifo.asm
index 4b147cb..b1cc25e 100644
--- a/PcAtChipsetPkg/PciHostBridgeDxe/Ia32/IoFifo.asm
+++ b/PcAtChipsetPkg/PciHostBridgeDxe/Ia32/IoFifo.asm
@@ -1,9 +1,10 @@
;------------------------------------------------------------------------------
;
; Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
-; This program and the accompanying materials
-; are licensed and made available under the terms and conditions of the BSD License
-; which accompanies this distribution. The full text of the license may be found at
+;
+; This program and the accompanying materials are licensed and made available
+; under the terms and conditions of the BSD License which accompanies this
+; distribution. The full text of the license may be found at
; http://opensource.org/licenses/bsd-license.php.
;
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/X64/IoFifo.S b/PcAtChipsetPkg/PciHostBridgeDxe/X64/IoFifo.S
index ca484f5..decb382 100644
--- a/PcAtChipsetPkg/PciHostBridgeDxe/X64/IoFifo.S
+++ b/PcAtChipsetPkg/PciHostBridgeDxe/X64/IoFifo.S
@@ -1,9 +1,10 @@
#------------------------------------------------------------------------------
#
# Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
-# This program and the accompanying materials
-# are licensed and made available under the terms and conditions of the BSD License
-# which accompanies this distribution. The full text of the license may be found at
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License which accompanies this
+# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php.
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/X64/IoFifo.asm b/PcAtChipsetPkg/PciHostBridgeDxe/X64/IoFifo.asm
index d16f024..1a3f0ef 100644
--- a/PcAtChipsetPkg/PciHostBridgeDxe/X64/IoFifo.asm
+++ b/PcAtChipsetPkg/PciHostBridgeDxe/X64/IoFifo.asm
@@ -1,9 +1,10 @@
;------------------------------------------------------------------------------
;
; Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
-; This program and the accompanying materials
-; are licensed and made available under the terms and conditions of the BSD License
-; which accompanies this distribution. The full text of the license may be found at
+;
+; This program and the accompanying materials are licensed and made available
+; under the terms and conditions of the BSD License which accompanies this
+; distribution. The full text of the license may be found at
; http://opensource.org/licenses/bsd-license.php.
;
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:07 UTC
Permalink
Cc: Ruiyu Ni <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
Reviewed-by: Ruiyu Ni <***@intel.com>
---

Notes:
v3:
- rewrap the driver under PcAtChipsetPkg

PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.c | 579 +++++++++++++-------
1 file changed, 368 insertions(+), 211 deletions(-)

diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.c b/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.c
index 2f6ef68..8b7b035 100644
--- a/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.c
+++ b/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.c
@@ -1,16 +1,18 @@
/** @file
- Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation
+ Provides the basic interfaces to abstract a PCI Host Bridge Resource
+ Allocation

-Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials are
-licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
+ Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>

-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php

-**/
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/

#include "PciHostBridge.h"

@@ -168,68 +170,114 @@ InitializePciHostBridge (


/**
- 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] This 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.
+ 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] This 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
EFIAPI
@@ -485,26 +533,38 @@ NotifyPhase(
}

/**
- Return the device handle of the next PCI root bridge that is associated with this Host Bridge.
+ Return the device handle of the next PCI root bridge that is associated with
+ this Host Bridge.

- This function is called multiple times to retrieve the device handles of all the PCI root bridges that
- are associated with this PCI host bridge. Each PCI host bridge is associated with one or more PCI
- root bridges. On each call, the handle that was returned by the previous call is passed into the
- interface, and on output the interface returns the device handle of the next PCI root bridge. The
- caller can use the handle to obtain the instance of the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
- for that root bridge. When there are no more PCI root bridges to report, the interface returns
- EFI_NOT_FOUND. A PCI enumerator must enumerate the PCI root bridges in the order that they
- are returned by this function.
- For D945 implementation, there is only one root bridge in PCI host bridge.
+ This function is called multiple times to retrieve the device handles of all
+ the PCI root bridges that are associated with this PCI host bridge. Each PCI
+ host bridge is associated with one or more PCI root bridges. On each call,
+ the handle that was returned by the previous call is passed into the
+ interface, and on output the interface returns the device handle of the next
+ PCI root bridge. The caller can use the handle to obtain the instance of the
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL for that root bridge. When there are no more
+ PCI root bridges to report, the interface returns EFI_NOT_FOUND. A PCI
+ enumerator must enumerate the PCI root bridges in the order that they are
+ returned by this function.

- @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
- @param[in, out] RootBridgeHandle Returns the device handle of the next PCI root bridge.
-
- @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then return the first Rootbridge handle of the
- specific Host bridge and return EFI_SUCCESS.
- @retval EFI_NOT_FOUND Can not find the any more root bridge in specific host bridge.
- @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was
- returned on a previous call to GetNextRootBridge().
+ For D945 implementation, there is only one root bridge in PCI host bridge.
+
+ @param[in] This The instance pointer of
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+
+ @param[in, out] RootBridgeHandle Returns the device handle of the next PCI
+ root bridge.
+
+ @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then
+ return the first Rootbridge handle of the
+ specific Host bridge and return EFI_SUCCESS.
+
+ @retval EFI_NOT_FOUND Can not find the any more root bridge in
+ specific host bridge.
+
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was
+ returned on a previous call to
+ GetNextRootBridge().
**/
EFI_STATUS
EFIAPI
@@ -559,42 +619,62 @@ GetNextRootBridge(
}

/**
- Returns the allocation attributes of a PCI root bridge.
-
- The function returns the allocation attributes of a specific PCI root bridge. The attributes can vary
- from one PCI root bridge to another. These attributes are different from the decode-related
- attributes that are returned by the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
- RootBridgeHandle parameter is used to specify the instance of the PCI root bridge. The device
- handles of all the root bridges that are associated with this host bridge must be obtained by calling
- GetNextRootBridge(). The attributes are static in the sense that they do not change during or
- after the enumeration process. The hardware may provide mechanisms to change the attributes on
- the fly, but such changes must be completed before EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is
- installed. The permitted values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
- "Related Definitions" below. The caller uses these attributes to combine multiple resource requests.
- For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI bus enumerator needs to
- include requests for the prefetchable memory in the nonprefetchable memory pool and not request any
- prefetchable memory.
- Attribute Description
- ------------------------------------ ----------------------------------------------------------------------
- EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root bridge does not support separate
- windows for nonprefetchable and prefetchable memory. A PCI bus
- driver needs to include requests for prefetchable memory in the
- nonprefetchable memory pool.
-
- EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root bridge supports 64-bit memory
- windows. If this bit is not set, the PCI bus driver needs to include
- requests for a 64-bit memory address in the corresponding 32-bit
- memory pool.
-
- @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
- @param[in] RootBridgeHandle The device handle of the PCI root bridge in which the caller is interested. Type
- EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
- @param[out] Attributes The pointer to attribte of root bridge, it is output parameter
-
- @retval EFI_INVALID_PARAMETER Attribute pointer is NULL
- @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid.
- @retval EFI_SUCCESS Success to get attribute of interested root bridge.
+ Returns the allocation attributes of a PCI root bridge.

+ The function returns the allocation attributes of a specific PCI root bridge.
+ The attributes can vary from one PCI root bridge to another. These attributes
+ are different from the decode-related attributes that are returned by the
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
+ RootBridgeHandle parameter is used to specify the instance of the PCI root
+ bridge. The device handles of all the root bridges that are associated with
+ this host bridge must be obtained by calling GetNextRootBridge(). The
+ attributes are static in the sense that they do not change during or after
+ the enumeration process. The hardware may provide mechanisms to change the
+ attributes on the fly, but such changes must be completed before
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is installed. The permitted
+ values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
+ "Related Definitions" below. The caller uses these attributes to combine
+ multiple resource requests.
+
+ For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI
+ bus enumerator needs to include requests for the prefetchable memory in the
+ nonprefetchable memory pool and not request any prefetchable memory.
+
+ Attribute Description
+ ------------------------------------ ---------------------------------------
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root
+ bridge does not support separate
+ windows for nonprefetchable and
+ prefetchable memory. A PCI bus driver
+ needs to include requests for
+ prefetchable memory in the
+ nonprefetchable memory pool.
+
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root
+ bridge supports 64-bit memory windows.
+ If this bit is not set, the PCI bus
+ driver needs to include requests for a
+ 64-bit memory address in the
+ corresponding 32-bit memory pool.
+
+ @param[in] This The instance pointer of
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+
+ @param[in] RootBridgeHandle The device handle of the PCI root bridge in
+ which the caller is interested. Type
+ EFI_HANDLE is defined in
+ InstallProtocolInterface() in the UEFI 2.0
+ Specification.
+
+ @param[out] Attributes The pointer to attribte of root bridge, it is
+ output parameter
+
+ @retval EFI_INVALID_PARAMETER Attribute pointer is NULL
+
+ @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid.
+
+ @retval EFI_SUCCESS Success to get attribute of interested root
+ bridge.
**/
EFI_STATUS
EFIAPI
@@ -632,19 +712,26 @@ GetAttributes(
}

/**
- Sets up the specified PCI root bridge for the bus enumeration process.
+ Sets up the specified PCI root bridge for the bus enumeration process.

- This member function sets up the root bridge for bus enumeration and returns the PCI bus range
- over which the search should be performed in ACPI 2.0 resource descriptor format.
+ This member function sets up the root bridge for bus enumeration and returns
+ the PCI bus range over which the search should be performed in ACPI 2.0
+ resource descriptor format.

- @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
- @param[in] RootBridgeHandle The PCI Root Bridge to be set up.
- @param[out] Configuration Pointer to the pointer to the PCI bus resource descriptor.
-
- @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
- @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag.
- @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor.
+ @param[in] This The
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ instance.

+ @param[in] RootBridgeHandle The PCI Root Bridge to be set up.
+
+ @param[out] Configuration Pointer to the pointer to the PCI bus resource
+ descriptor.
+
+ @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
+
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag.
+
+ @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor.
**/
EFI_STATUS
EFIAPI
@@ -709,28 +796,50 @@ StartBusEnumeration(
}

/**
- Programs the PCI root bridge hardware so that it decodes the specified PCI bus range.
-
- This member function programs the specified PCI root bridge to decode the bus range that is
- specified by the input parameter Configuration.
- The bus range information is specified in terms of the ACPI 2.0 resource descriptor format.
-
- @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
- @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed
- @param[in] Configuration The pointer to the PCI bus resource descriptor
-
- @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
- @retval EFI_INVALID_PARAMETER Configuration is NULL.
- @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.
- @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI 2.0 bus resource descriptor.
- @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource descriptors other than
- bus descriptors.
- @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid ACPI resource descriptors.
- @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this root bridge.
- @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this root bridge.
- @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
- @retval EFI_SUCCESS The bus range for the PCI root bridge was programmed.
+ Programs the PCI root bridge hardware so that it decodes the specified PCI
+ bus range.

+ This member function programs the specified PCI root bridge to decode the bus
+ range that is specified by the input parameter Configuration.
+ The bus range information is specified in terms of the ACPI 2.0 resource
+ descriptor format.
+
+ @param[in] This The
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ instance
+
+ @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be
+ programmed
+
+ @param[in] Configuration The pointer to the PCI bus resource descriptor
+
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
+ handle.
+
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+
+ @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI
+ 2.0 resource descriptor.
+
+ @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI
+ 2.0 bus resource descriptor.
+
+ @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource
+ descriptors other than bus descriptors.
+
+ @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid
+ ACPI resource descriptors.
+
+ @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this
+ root bridge.
+
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
+
+ @retval EFI_SUCCESS The bus range for the PCI root bridge was
+ programmed.
**/
EFI_STATUS
EFIAPI
@@ -812,29 +921,50 @@ SetBusNumbers(


/**
- Submits the I/O and memory resource requirements for the specified PCI root bridge.
-
- This function is used to submit all the I/O and memory resources that are required by the specified
- PCI root bridge. The input parameter Configuration is used to specify the following:
- - The various types of resources that are required
- - The associated lengths in terms of ACPI 2.0 resource descriptor format
-
- @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
- @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory resource requirements are being submitted.
- @param[in] Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
-
- @retval EFI_SUCCESS The I/O and memory resource requests for a PCI root bridge were accepted.
- @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
- @retval EFI_INVALID_PARAMETER Configuration is NULL.
- @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.
- @retval EFI_INVALID_PARAMETER Configuration includes requests for one or more resource types that are
- not supported by this PCI root bridge. This error will happen if the caller
- did not combine resources according to Attributes that were returned by
- GetAllocAttributes().
- @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid.
- @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI root bridge.
- @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for this PCI root bridge.
+ Submits the I/O and memory resource requirements for the specified PCI root
+ bridge.

+ This function is used to submit all the I/O and memory resources that are
+ required by the specified PCI root bridge. The input parameter Configuration
+ is used to specify the following:
+ - The various types of resources that are required
+ - The associated lengths in terms of ACPI 2.0 resource descriptor format
+
+ @param[in] This Pointer to the
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ instance.
+
+ @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory
+ resource requirements are being submitted.
+
+ @param[in] Configuration The pointer to the PCI I/O and PCI memory
+ resource descriptor.
+
+ @retval EFI_SUCCESS The I/O and memory resource requests for a PCI
+ root bridge were accepted.
+
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
+ handle.
+
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+
+ @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI
+ 2.0 resource descriptor.
+
+ @retval EFI_INVALID_PARAMETER Configuration includes requests for one or
+ more resource types that are not supported by
+ this PCI root bridge. This error will happen
+ if the caller did not combine resources
+ according to Attributes that were returned by
+ GetAllocAttributes().
+
+ @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid.
+
+ @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for
+ this PCI root bridge.
**/
EFI_STATUS
EFIAPI
@@ -963,22 +1093,34 @@ SubmitResources(
/**
Returns the proposed resource settings for the specified PCI root bridge.

- This member function returns the proposed resource settings for the specified PCI root bridge. The
- proposed resource settings are prepared when NotifyPhase() is called with a Phase of
- EfiPciHostBridgeAllocateResources. The output parameter Configuration
- specifies the following:
- - The various types of resources, excluding bus resources, that are allocated
+ This member function returns the proposed resource settings for the
+ specified PCI root bridge. The proposed resource settings are prepared when
+ NotifyPhase() is called with a Phase of EfiPciHostBridgeAllocateResources.
+ The output parameter Configuration specifies the following:
+ - The various types of resources, excluding bus resources, that are
+ allocated
- The associated lengths in terms of ACPI 2.0 resource descriptor format

- @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
- @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
- @param[out] Configuration The pointer to the pointer to the PCI I/O and memory resource descriptor.
-
+ @param[in] This Pointer to the
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ instance.
+
+ @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is
+ defined in InstallProtocolInterface() in the
+ UEFI 2.0 Specification.
+
+ @param[out] Configuration The pointer to the pointer to the PCI I/O and
+ memory resource descriptor.
+
@retval EFI_SUCCESS The requested parameters were returned.
- @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
+ handle.
+
@retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.

+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -1136,31 +1278,46 @@ GetProposedResources(
}

/**
- 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 This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
- @param RootBridgeHandle The associated PCI root bridge handle. Type EFI_HANDLE is defined in
- InstallProtocolInterface() in the UEFI 2.0 Specification.
- @param PciAddress The address of the PCI device on the PCI bus. This address can be passed to the
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to access the PCI
- configuration space of the device. See Table 12-1 in the UEFI 2.0 Specification for
- the definition of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
- @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.
+ 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 This Pointer to the
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ instance.
+
+ @param RootBridgeHandle The associated PCI root bridge handle. Type
+ EFI_HANDLE is defined in InstallProtocolInterface()
+ in the UEFI 2.0 Specification.
+
+ @param PciAddress The address of the PCI device on the PCI bus. This
+ address can be passed to the
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to
+ access the PCI configuration space of the device.
+ See Table 12-1 in the UEFI 2.0 Specification for the
+ definition of
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
+
+ @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
EFIAPI
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:11 UTC
Permalink
The source code is copied verbatim, with the following two exceptions:
- the UNI files are dropped, together with the corresponding UNI
references in the INF file,
- the INF file receives a new FILE_GUID.

The OVMF DSC and FDF files are at once flipped to the cloned driver.

Cc: Jordan Justen <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
---
{PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/PciHostBridgeDxe.inf | 6 +-----
{PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/IoFifo.h | 0
{PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/PciHostBridge.h | 0
{PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/PciHostBridge.c | 0
{PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/PciRootBridgeIo.c | 0
OvmfPkg/OvmfPkgIa32.dsc | 2 +-
OvmfPkg/OvmfPkgIa32.fdf | 2 +-
OvmfPkg/OvmfPkgIa32X64.dsc | 2 +-
OvmfPkg/OvmfPkgIa32X64.fdf | 2 +-
OvmfPkg/OvmfPkgX64.dsc | 2 +-
OvmfPkg/OvmfPkgX64.fdf | 2 +-
{PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/Ia32/IoFifo.S | 0
{PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/Ia32/IoFifo.asm | 0
{PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/X64/IoFifo.S | 0
{PcAtChipsetPkg => OvmfPkg}/PciHostBridgeDxe/X64/IoFifo.asm | 0
15 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf b/OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
similarity index 85%
copy from PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
copy to OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
index be3622b..40f4c3c 100644
--- a/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
@@ -18,8 +18,7 @@
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PciHostBridge
- MODULE_UNI_FILE = PciHostBridge.uni
- FILE_GUID = 2383608E-C6D0-4e3e-858D-45DFAC3543D5
+ FILE_GUID = 311161C5-BFD9-4504-8016-213F2DAEDAF3
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0

@@ -63,6 +62,3 @@ [Protocols]

[depex]
gEfiMetronomeArchProtocolGuid
-
-[UserExtensions.TianoCore."ExtraFiles"]
- PciHostBridgeExtra.uni
diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/IoFifo.h b/OvmfPkg/PciHostBridgeDxe/IoFifo.h
similarity index 100%
copy from PcAtChipsetPkg/PciHostBridgeDxe/IoFifo.h
copy to OvmfPkg/PciHostBridgeDxe/IoFifo.h
diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.h b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
similarity index 100%
copy from PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.h
copy to OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.c b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
similarity index 100%
copy from PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.c
copy to OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c b/OvmfPkg/PciHostBridgeDxe/PciRootBridgeIo.c
similarity index 100%
copy from PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c
copy to OvmfPkg/PciHostBridgeDxe/PciRootBridgeIo.c
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 642b319..2775661 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -453,7 +453,7 @@ [Components]
UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
UefiCpuPkg/CpuDxe/CpuDxe.inf
PcAtChipsetPkg/8254TimerDxe/8254Timer.inf
- PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
+ OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
<LibraryClasses>
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
index 24ad0bf..9d020d5 100644
--- a/OvmfPkg/OvmfPkgIa32.fdf
+++ b/OvmfPkg/OvmfPkgIa32.fdf
@@ -214,7 +214,7 @@ [FV.DXEFV]
INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
INF UefiCpuPkg/CpuDxe/CpuDxe.inf
INF PcAtChipsetPkg/8254TimerDxe/8254Timer.inf
-INF PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
+INF OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
INF PcAtChipsetPkg/KbcResetDxe/Reset.inf
INF MdeModulePkg/Universal/Metronome/Metronome.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 819f52e..8514327 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -460,7 +460,7 @@ [Components.X64]
UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
UefiCpuPkg/CpuDxe/CpuDxe.inf
PcAtChipsetPkg/8254TimerDxe/8254Timer.inf
- PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
+ OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
<LibraryClasses>
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
index 5f98be8..1835631 100644
--- a/OvmfPkg/OvmfPkgIa32X64.fdf
+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
@@ -214,7 +214,7 @@ [FV.DXEFV]
INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
INF UefiCpuPkg/CpuDxe/CpuDxe.inf
INF PcAtChipsetPkg/8254TimerDxe/8254Timer.inf
-INF PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
+INF OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
INF PcAtChipsetPkg/KbcResetDxe/Reset.inf
INF MdeModulePkg/Universal/Metronome/Metronome.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 878daf0..9e252f3 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -458,7 +458,7 @@ [Components]
UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
UefiCpuPkg/CpuDxe/CpuDxe.inf
PcAtChipsetPkg/8254TimerDxe/8254Timer.inf
- PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
+ OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
<LibraryClasses>
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index 11e74e7..b82eeba 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -214,7 +214,7 @@ [FV.DXEFV]
INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
INF UefiCpuPkg/CpuDxe/CpuDxe.inf
INF PcAtChipsetPkg/8254TimerDxe/8254Timer.inf
-INF PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
+INF OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
INF PcAtChipsetPkg/KbcResetDxe/Reset.inf
INF MdeModulePkg/Universal/Metronome/Metronome.inf
diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/Ia32/IoFifo.S b/OvmfPkg/PciHostBridgeDxe/Ia32/IoFifo.S
similarity index 100%
copy from PcAtChipsetPkg/PciHostBridgeDxe/Ia32/IoFifo.S
copy to OvmfPkg/PciHostBridgeDxe/Ia32/IoFifo.S
diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/Ia32/IoFifo.asm b/OvmfPkg/PciHostBridgeDxe/Ia32/IoFifo.asm
similarity index 100%
copy from PcAtChipsetPkg/PciHostBridgeDxe/Ia32/IoFifo.asm
copy to OvmfPkg/PciHostBridgeDxe/Ia32/IoFifo.asm
diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/X64/IoFifo.S b/OvmfPkg/PciHostBridgeDxe/X64/IoFifo.S
similarity index 100%
copy from PcAtChipsetPkg/PciHostBridgeDxe/X64/IoFifo.S
copy to OvmfPkg/PciHostBridgeDxe/X64/IoFifo.S
diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/X64/IoFifo.asm b/OvmfPkg/PciHostBridgeDxe/X64/IoFifo.asm
similarity index 100%
copy from PcAtChipsetPkg/PciHostBridgeDxe/X64/IoFifo.asm
copy to OvmfPkg/PciHostBridgeDxe/X64/IoFifo.asm
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:12 UTC
Permalink
These messages are helpful for comparing the assignments made by OVMF
against those made by SeaBIOS. To SeaBIOS a small debug patch like the
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index ac39d23..9e61c22 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -308,8 +308,12 @@ static void pci_bios_init_device(struct pci_device *pci)
/* map the interrupt */
int pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
- if (pin != 0)
- pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pci_slot_get_irq(pci, pin));
+ if (pin != 0) {
+ int irqline = pci_slot_get_irq(pci, pin);
+
+ pci_config_writeb(bdf, PCI_INTERRUPT_LINE, irqline);
+ dprintf(1, "assigned irq line %d\n", irqline);
+ }
pci_init_device(pci_device_tbl, pci, NULL);
Cc: Jordan Justen <***@intel.com>
Cc: Gabriel Somlo <***@cmu.edu>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Acked-by: Gabriel Somlo <***@cmu.edu>
---

Notes:
v2:
- use PciIo.GetLocation() too, in order to get an output more easily comparable
with SeaBIOS's
- drop Gabriel's Regression-tested-by

OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c | 25 ++++++++++++++++++++
1 file changed, 25 insertions(+)

diff --git a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
index 1eb2a8b..fdae6b1 100644
--- a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
+++ b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
@@ -749,6 +749,7 @@ SetPciIntLine (
)
{
EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
UINTN RootSlot;
UINTN Idx;
UINT8 IrqLine;
@@ -760,6 +761,7 @@ SetPciIntLine (

DevPathNode = DevicePathFromHandle (Handle);
ASSERT (DevPathNode != NULL);
+ DevPath = DevPathNode;

//
// Compute index into PciHostIrqs[] table by walking
@@ -832,6 +834,29 @@ SetPciIntLine (
Idx %= ARRAY_SIZE (PciHostIrqs);
IrqLine = PciHostIrqs[Idx];

+ DEBUG_CODE_BEGIN ();
+ {
+ CHAR16 *DevPathString;
+ STATIC CHAR16 Fallback[] = L"<failed to convert>";
+ UINTN Segment, Bus, Device, Function;
+
+ DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);
+ if (DevPathString == NULL) {
+ DevPathString = Fallback;
+ }
+ Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((EFI_D_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,
+ (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,
+ IrqLine));
+
+ if (DevPathString != Fallback) {
+ FreePool (DevPathString);
+ }
+ }
+ DEBUG_CODE_END ();
+
//
// Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
//
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:08 UTC
Permalink
In this patch the code and the comments embedded in code are rewrapped to
79 columns, plus any trailing whitespace is stripped.

Cc: Ruiyu Ni <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
Reviewed-by: Ruiyu Ni <***@intel.com>
---

Notes:
v3:
- rewrap the driver under PcAtChipsetPkg

PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.c | 397 +++++++++++---------
1 file changed, 218 insertions(+), 179 deletions(-)

diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.c b/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.c
index 8b7b035..aa02641 100644
--- a/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.c
+++ b/PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.c
@@ -24,7 +24,9 @@
//
UINTN RootBridgeNumber[1] = { 1 };

-UINT64 RootBridgeAttribute[1][1] = { { EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM } };
+UINT64 RootBridgeAttribute[1][1] = {
+ { EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM }
+};

EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[1][1] = {
{
@@ -41,7 +43,7 @@ EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[1][1] = {
EISA_PNP_ID(0x0A03),
0
},
-
+
{
END_DEVICE_PATH_TYPE,
END_ENTIRE_DEVICE_PATH_SUBTYPE,
@@ -105,35 +107,37 @@ InitializePciHostBridge (
UINTN Loop2;
PCI_HOST_BRIDGE_INSTANCE *HostBridge;
PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
-
+
mDriverImageHandle = ImageHandle;
-
+
//
// Create Host Bridge Device Handle
//
for (Loop1 = 0; Loop1 < HOST_BRIDGE_NUMBER; Loop1++) {
- HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE), &mPciHostBridgeInstanceTemplate);
+ HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE),
+ &mPciHostBridgeInstanceTemplate);
if (HostBridge == NULL) {
return EFI_OUT_OF_RESOURCES;
}
-
+
HostBridge->RootBridgeNumber = RootBridgeNumber[Loop1];
InitializeListHead (&HostBridge->Head);

Status = gBS->InstallMultipleProtocolInterfaces (
- &HostBridge->HostBridgeHandle,
- &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
+ &HostBridge->HostBridgeHandle,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid,
+ &HostBridge->ResAlloc,
NULL
);
if (EFI_ERROR (Status)) {
FreePool (HostBridge);
return EFI_DEVICE_ERROR;
}
-
+
//
// Create Root Bridge Device Handle in this Host Bridge
//
-
+
for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) {
PrivateData = AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE));
if (PrivateData == NULL) {
@@ -141,29 +145,32 @@ InitializePciHostBridge (
}

PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
- PrivateData->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Loop1][Loop2];
+ PrivateData->DevicePath =
+ (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Loop1][Loop2];

RootBridgeConstructor (
- &PrivateData->Io,
- HostBridge->HostBridgeHandle,
- RootBridgeAttribute[Loop1][Loop2],
+ &PrivateData->Io,
+ HostBridge->HostBridgeHandle,
+ RootBridgeAttribute[Loop1][Loop2],
&mResAperture[Loop1][Loop2]
);
-
+
Status = gBS->InstallMultipleProtocolInterfaces(
- &PrivateData->Handle,
- &gEfiDevicePathProtocolGuid, PrivateData->DevicePath,
- &gEfiPciRootBridgeIoProtocolGuid, &PrivateData->Io,
+ &PrivateData->Handle,
+ &gEfiDevicePathProtocolGuid,
+ PrivateData->DevicePath,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ &PrivateData->Io,
NULL
);
if (EFI_ERROR (Status)) {
FreePool(PrivateData);
return EFI_DEVICE_ERROR;
}
-
+
InsertTailList (&HostBridge->Head, &PrivateData->Link);
}
- }
+ }

return EFI_SUCCESS;
}
@@ -295,18 +302,18 @@ NotifyPhase(
UINTN BitsOfAlignment;
EFI_STATUS Status;
EFI_STATUS ReturnStatus;
-
+
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
-
+
switch (Phase) {

case EfiPciHostBridgeBeginEnumeration:
if (HostBridgeInstance->CanRestarted) {
//
- // Reset the Each Root Bridge
+ // Reset the Each Root Bridge
//
List = HostBridgeInstance->Head.ForwardLink;
-
+
while (List != &HostBridgeInstance->Head) {
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
for (Index = TypeIo; Index < TypeMax; Index++) {
@@ -315,18 +322,18 @@ NotifyPhase(
RootBridgeInstance->ResAllocNode[Index].Length = 0;
RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
}
-
+
List = List->ForwardLink;
}
-
+
HostBridgeInstance->ResourceSubmited = FALSE;
HostBridgeInstance->CanRestarted = TRUE;
} else {
//
// Can not restart
- //
+ //
return EFI_NOT_READY;
- }
+ }
break;

case EfiPciHostBridgeEndEnumeration:
@@ -334,21 +341,24 @@ NotifyPhase(

case EfiPciHostBridgeBeginBusAllocation:
//
- // No specific action is required here, can perform any chipset specific programing
+ // No specific action is required here, can perform any chipset specific
+ // programing
//
HostBridgeInstance->CanRestarted = FALSE;
break;

case EfiPciHostBridgeEndBusAllocation:
//
- // No specific action is required here, can perform any chipset specific programing
+ // No specific action is required here, can perform any chipset specific
+ // programing
//
//HostBridgeInstance->CanRestarted = FALSE;
break;

case EfiPciHostBridgeBeginResourceAllocation:
//
- // No specific action is required here, can perform any chipset specific programing
+ // No specific action is required here, can perform any chipset specific
+ // programing
//
//HostBridgeInstance->CanRestarted = FALSE;
break;
@@ -357,7 +367,7 @@ NotifyPhase(
ReturnStatus = EFI_SUCCESS;
if (HostBridgeInstance->ResourceSubmited) {
//
- // Take care of the resource dependencies between the root bridges
+ // Take care of the resource dependencies between the root bridges
//
List = HostBridgeInstance->Head.ForwardLink;

@@ -365,17 +375,20 @@ NotifyPhase(
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
for (Index = TypeIo; Index < TypeBus; Index++) {
if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
-
+
AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
-
+
//
// Get the number of '1' in Alignment.
//
- BitsOfAlignment = (UINTN) (HighBitSet64 (RootBridgeInstance->ResAllocNode[Index].Alignment) + 1);
-
+ BitsOfAlignment =
+ (UINTN)(HighBitSet64 (
+ RootBridgeInstance->ResAllocNode[Index].Alignment
+ ) + 1);
+
switch (Index) {

- case TypeIo:
+ case TypeIo:
//
// It is impossible for this chipset to align 0xFFFF for IO16
// So clear it
@@ -383,22 +396,24 @@ NotifyPhase(
if (BitsOfAlignment >= 16) {
BitsOfAlignment = 0;
}
-
+
Status = gDS->AllocateIoSpace (
- EfiGcdAllocateAnySearchBottomUp,
- EfiGcdIoTypeIo,
+ EfiGcdAllocateAnySearchBottomUp,
+ EfiGcdIoTypeIo,
BitsOfAlignment,
AddrLen,
&BaseAddress,
mDriverImageHandle,
NULL
);
-
+
if (!EFI_ERROR (Status)) {
- RootBridgeInstance->ResAllocNode[Index].Base = (UINTN)BaseAddress;
- RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
+ RootBridgeInstance->ResAllocNode[Index].Base =
+ (UINTN)BaseAddress;
+ RootBridgeInstance->ResAllocNode[Index].Status =
+ ResAllocated;
} else {
- ReturnStatus = Status;
+ ReturnStatus = Status;
if (Status != EFI_OUT_OF_RESOURCES) {
RootBridgeInstance->ResAllocNode[Index].Length = 0;
}
@@ -409,55 +424,58 @@ NotifyPhase(

case TypeMem32:
//
- // It is impossible for this chipset to align 0xFFFFFFFF for Mem32
- // So clear it
+ // It is impossible for this chipset to align 0xFFFFFFFF for
+ // Mem32
+ // So clear it
//
-
+
if (BitsOfAlignment >= 32) {
BitsOfAlignment = 0;
}
-
+
Status = gDS->AllocateMemorySpace (
- EfiGcdAllocateAnySearchBottomUp,
- EfiGcdMemoryTypeMemoryMappedIo,
+ EfiGcdAllocateAnySearchBottomUp,
+ EfiGcdMemoryTypeMemoryMappedIo,
BitsOfAlignment,
AddrLen,
&BaseAddress,
mDriverImageHandle,
NULL
);
-
+
if (!EFI_ERROR (Status)) {
// We were able to allocate the PCI memory
- RootBridgeInstance->ResAllocNode[Index].Base = (UINTN)BaseAddress;
- RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
-
+ RootBridgeInstance->ResAllocNode[Index].Base =
+ (UINTN)BaseAddress;
+ RootBridgeInstance->ResAllocNode[Index].Status =
+ ResAllocated;
+
} else {
// Not able to allocate enough PCI memory
- ReturnStatus = Status;
-
+ ReturnStatus = Status;
+
if (Status != EFI_OUT_OF_RESOURCES) {
RootBridgeInstance->ResAllocNode[Index].Length = 0;
- }
+ }
ASSERT (FALSE);
}
break;
-
- case TypePMem32:
- case TypeMem64:
+
+ case TypePMem32:
+ case TypeMem64:
case TypePMem64:
ReturnStatus = EFI_ABORTED;
- break;
+ break;
default:
ASSERT (FALSE);
break;
}; //end switch
}
}
-
+
List = List->ForwardLink;
}
-
+
return ReturnStatus;

} else {
@@ -479,8 +497,8 @@ NotifyPhase(
BaseAddress = RootBridgeInstance->ResAllocNode[Index].Base;
switch (Index) {

- case TypeIo:
- Status = gDS->FreeIoSpace (BaseAddress, AddrLen);
+ case TypeIo:
+ Status = gDS->FreeIoSpace (BaseAddress, AddrLen);
if (EFI_ERROR (Status)) {
ReturnStatus = Status;
}
@@ -500,7 +518,7 @@ NotifyPhase(
break;

case TypePMem64:
- break;
+ break;

default:
ASSERT (FALSE);
@@ -513,12 +531,12 @@ NotifyPhase(
RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
}
}
-
+
List = List->ForwardLink;
}
-
+
HostBridgeInstance->ResourceSubmited = FALSE;
- HostBridgeInstance->CanRestarted = TRUE;
+ HostBridgeInstance->CanRestarted = TRUE;
return ReturnStatus;

case EfiPciHostBridgeEndResourceAllocation:
@@ -528,8 +546,8 @@ NotifyPhase(
default:
return EFI_INVALID_PARAMETER;
}
-
- return EFI_SUCCESS;
+
+ return EFI_SUCCESS;
}

/**
@@ -573,16 +591,16 @@ GetNextRootBridge(
IN OUT EFI_HANDLE *RootBridgeHandle
)
{
- BOOLEAN NoRootBridge;
- LIST_ENTRY *List;
+ BOOLEAN NoRootBridge;
+ LIST_ENTRY *List;
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
-
+
NoRootBridge = TRUE;
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
List = HostBridgeInstance->Head.ForwardLink;
-
-
+
+
while (List != &HostBridgeInstance->Head) {
NoRootBridge = FALSE;
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
@@ -601,16 +619,16 @@ GetNextRootBridge(
if (List!=&HostBridgeInstance->Head) {
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
*RootBridgeHandle = RootBridgeInstance->Handle;
- return EFI_SUCCESS;
+ return EFI_SUCCESS;
} else {
return EFI_NOT_FOUND;
}
}
}
-
+
List = List->ForwardLink;
} //end while
-
+
if (NoRootBridge) {
return EFI_NOT_FOUND;
} else {
@@ -684,17 +702,17 @@ GetAttributes(
OUT UINT64 *Attributes
)
{
- LIST_ENTRY *List;
+ LIST_ENTRY *List;
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
-
+
if (Attributes == NULL) {
return EFI_INVALID_PARAMETER;
}
-
+
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
List = HostBridgeInstance->Head.ForwardLink;
-
+
while (List != &HostBridgeInstance->Head) {
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
if (RootBridgeHandle == RootBridgeInstance->Handle) {
@@ -703,9 +721,9 @@ GetAttributes(
}
List = List->ForwardLink;
}
-
+
//
- // RootBridgeHandle is not an EFI_HANDLE
+ // RootBridgeHandle is not an EFI_HANDLE
// that was returned on a previous call to GetNextRootBridge()
//
return EFI_INVALID_PARAMETER;
@@ -741,17 +759,17 @@ StartBusEnumeration(
OUT VOID **Configuration
)
{
- LIST_ENTRY *List;
+ LIST_ENTRY *List;
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
VOID *Buffer;
UINT8 *Temp;
UINT64 BusStart;
UINT64 BusEnd;
-
+
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
List = HostBridgeInstance->Head.ForwardLink;
-
+
while (List != &HostBridgeInstance->Head) {
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
if (RootBridgeHandle == RootBridgeInstance->Handle) {
@@ -763,35 +781,39 @@ StartBusEnumeration(
//
// Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
//
-
- Buffer = AllocatePool (sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR));
+
+ Buffer = AllocatePool (
+ sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
+ sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)
+ );
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
-
+
Temp = (UINT8 *)Buffer;
-
+
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Desc = 0x8A;
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Len = 0x2B;
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->ResType = 2;
- ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->GenFlag = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->GenFlag = 0;
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->SpecificFlag = 0;
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrSpaceGranularity = 0;
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMin = BusStart;
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMax = 0;
- ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrTranslationOffset = 0;
- ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrLen = BusEnd - BusStart + 1;
-
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrTranslationOffset = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrLen =
+ BusEnd - BusStart + 1;
+
Temp = Temp + sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
- ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
-
- *Configuration = Buffer;
+
+ *Configuration = Buffer;
return EFI_SUCCESS;
}
List = List->ForwardLink;
}
-
+
return EFI_INVALID_PARAMETER;
}

@@ -849,27 +871,27 @@ SetBusNumbers(
IN VOID *Configuration
)
{
- LIST_ENTRY *List;
+ LIST_ENTRY *List;
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
UINT8 *Ptr;
UINTN BusStart;
UINTN BusEnd;
UINTN BusLen;
-
+
if (Configuration == NULL) {
return EFI_INVALID_PARAMETER;
}
-
+
Ptr = Configuration;
-
+
//
// Check the Configuration is valid
//
if(*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
return EFI_INVALID_PARAMETER;
}
-
+
if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != 2) {
return EFI_INVALID_PARAMETER;
}
@@ -878,44 +900,48 @@ SetBusNumbers(
if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {
return EFI_INVALID_PARAMETER;
}
-
+
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
List = HostBridgeInstance->Head.ForwardLink;
-
+
Ptr = Configuration;
-
+
while (List != &HostBridgeInstance->Head) {
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
if (RootBridgeHandle == RootBridgeInstance->Handle) {
- BusStart = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin;
- BusLen = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
+
+ Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
+ BusStart = (UINTN)Desc->AddrRangeMin;
+ BusLen = (UINTN)Desc->AddrLen;
BusEnd = BusStart + BusLen - 1;
-
+
if (BusStart > BusEnd) {
return EFI_INVALID_PARAMETER;
}
-
- if ((BusStart < RootBridgeInstance->BusBase) || (BusEnd > RootBridgeInstance->BusLimit)) {
+
+ if ((BusStart < RootBridgeInstance->BusBase) ||
+ (BusEnd > RootBridgeInstance->BusLimit)) {
return EFI_INVALID_PARAMETER;
}
-
+
//
// Update the Bus Range
//
RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart;
RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;
RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;
-
+
//
// Program the Root Bridge Hardware
//
-
+
return EFI_SUCCESS;
}
-
+
List = List->ForwardLink;
}
-
+
return EFI_INVALID_PARAMETER;
}

@@ -974,32 +1000,32 @@ SubmitResources(
IN VOID *Configuration
)
{
- LIST_ENTRY *List;
+ LIST_ENTRY *List;
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
UINT8 *Temp;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
UINT64 AddrLen;
UINT64 Alignment;
-
+
//
// Check the input parameter: Configuration
//
if (Configuration == NULL) {
return EFI_INVALID_PARAMETER;
}
-
+
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
List = HostBridgeInstance->Head.ForwardLink;
-
+
Temp = (UINT8 *)Configuration;
- while ( *Temp == 0x8A) {
+ while ( *Temp == 0x8A) {
Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
}
if (*Temp != 0x79) {
return EFI_INVALID_PARAMETER;
}
-
+
Temp = (UINT8 *)Configuration;
while (List != &HostBridgeInstance->Head) {
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
@@ -1017,29 +1043,32 @@ SubmitResources(
//
// Check address range alignment
//
- if (Ptr->AddrRangeMax >= 0xffffffff || Ptr->AddrRangeMax != (GetPowerOfTwo64 (Ptr->AddrRangeMax + 1) - 1)) {
+ if (Ptr->AddrRangeMax >= 0xffffffff ||
+ Ptr->AddrRangeMax != (GetPowerOfTwo64 (
+ Ptr->AddrRangeMax + 1) - 1)) {
return EFI_INVALID_PARAMETER;
}
-
+
switch (Ptr->ResType) {

case 0:
-
+
//
// Check invalid Address Sapce Granularity
//
if (Ptr->AddrSpaceGranularity != 32) {
return EFI_INVALID_PARAMETER;
}
-
+
//
// check the memory resource request is supported by PCI root bridge
//
- if (RootBridgeInstance->RootBridgeAttrib == EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM &&
- Ptr->SpecificFlag == 0x06) {
+ if (RootBridgeInstance->RootBridgeAttrib ==
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM &&
+ Ptr->SpecificFlag == 0x06) {
return EFI_INVALID_PARAMETER;
}
-
+
AddrLen = Ptr->AddrLen;
Alignment = Ptr->AddrRangeMax;
if (Ptr->AddrSpaceGranularity == 32) {
@@ -1047,20 +1076,25 @@ SubmitResources(
//
// Apply from GCD
//
- RootBridgeInstance->ResAllocNode[TypePMem32].Status = ResSubmitted;
+ RootBridgeInstance->ResAllocNode[TypePMem32].Status =
+ ResSubmitted;
} else {
RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen;
- RootBridgeInstance->ResAllocNode[TypeMem32].Alignment = Alignment;
- RootBridgeInstance->ResAllocNode[TypeMem32].Status = ResRequested;
+ RootBridgeInstance->ResAllocNode[TypeMem32].Alignment =
+ Alignment;
+ RootBridgeInstance->ResAllocNode[TypeMem32].Status =
+ ResRequested;
HostBridgeInstance->ResourceSubmited = TRUE;
}
}

if (Ptr->AddrSpaceGranularity == 64) {
if (Ptr->SpecificFlag == 0x06) {
- RootBridgeInstance->ResAllocNode[TypePMem64].Status = ResSubmitted;
+ RootBridgeInstance->ResAllocNode[TypePMem64].Status =
+ ResSubmitted;
} else {
- RootBridgeInstance->ResAllocNode[TypeMem64].Status = ResSubmitted;
+ RootBridgeInstance->ResAllocNode[TypeMem64].Status =
+ ResSubmitted;
}
}
break;
@@ -1071,22 +1105,22 @@ SubmitResources(
RootBridgeInstance->ResAllocNode[TypeIo].Length = AddrLen;
RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment;
RootBridgeInstance->ResAllocNode[TypeIo].Status = ResRequested;
- HostBridgeInstance->ResourceSubmited = TRUE;
+ HostBridgeInstance->ResourceSubmited = TRUE;
break;

default:
break;
};
-
+
Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
- }
-
+ }
+
return EFI_SUCCESS;
}
-
+
List = List->ForwardLink;
}
-
+
return EFI_INVALID_PARAMETER;
}

@@ -1130,16 +1164,16 @@ GetProposedResources(
OUT VOID **Configuration
)
{
- LIST_ENTRY *List;
+ LIST_ENTRY *List;
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
UINTN Index;
- UINTN Number;
- VOID *Buffer;
+ UINTN Number;
+ VOID *Buffer;
UINT8 *Temp;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
UINT64 ResStatus;
-
+
Buffer = NULL;
Number = 0;
//
@@ -1147,7 +1181,7 @@ GetProposedResources(
//
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
List = HostBridgeInstance->Head.ForwardLink;
-
+
//
// Enumerate the root bridges in this host bridge
//
@@ -1157,24 +1191,27 @@ GetProposedResources(
for (Index = 0; Index < TypeBus; Index ++) {
if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
Number ++;
- }
+ }
}
-
+
if (Number == 0) {
return EFI_INVALID_PARAMETER;
}

- Buffer = AllocateZeroPool (Number * sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR));
+ Buffer = AllocateZeroPool (
+ Number * sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
+ sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)
+ );
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
-
+
Temp = Buffer;
for (Index = 0; Index < TypeBus; Index ++) {
if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;
-
+
switch (Index) {

case TypeIo:
@@ -1184,29 +1221,31 @@ GetProposedResources(
Ptr->Desc = 0x8A;
Ptr->Len = 0x2B;
Ptr->ResType = 1;
- Ptr->GenFlag = 0;
+ Ptr->GenFlag = 0;
Ptr->SpecificFlag = 0;
Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
Ptr->AddrRangeMax = 0;
- Ptr->AddrTranslationOffset = \
- (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ Ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ?
+ EFI_RESOURCE_SATISFIED :
+ EFI_RESOURCE_LESS;
Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
break;

case TypeMem32:
//
// Memory 32
- //
+ //
Ptr->Desc = 0x8A;
Ptr->Len = 0x2B;
Ptr->ResType = 0;
- Ptr->GenFlag = 0;
+ Ptr->GenFlag = 0;
Ptr->SpecificFlag = 0;
Ptr->AddrSpaceGranularity = 32;
Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
Ptr->AddrRangeMax = 0;
- Ptr->AddrTranslationOffset = \
- (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
+ Ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ?
+ EFI_RESOURCE_SATISFIED :
+ EFI_RESOURCE_LESS;
Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
break;

@@ -1217,12 +1256,12 @@ GetProposedResources(
Ptr->Desc = 0x8A;
Ptr->Len = 0x2B;
Ptr->ResType = 0;
- Ptr->GenFlag = 0;
+ Ptr->GenFlag = 0;
Ptr->SpecificFlag = 6;
Ptr->AddrSpaceGranularity = 32;
Ptr->AddrRangeMin = 0;
Ptr->AddrRangeMax = 0;
- Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
+ Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
Ptr->AddrLen = 0;
break;

@@ -1233,12 +1272,12 @@ GetProposedResources(
Ptr->Desc = 0x8A;
Ptr->Len = 0x2B;
Ptr->ResType = 0;
- Ptr->GenFlag = 0;
+ Ptr->GenFlag = 0;
Ptr->SpecificFlag = 0;
Ptr->AddrSpaceGranularity = 64;
Ptr->AddrRangeMin = 0;
Ptr->AddrRangeMax = 0;
- Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
+ Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
Ptr->AddrLen = 0;
break;

@@ -1249,31 +1288,31 @@ GetProposedResources(
Ptr->Desc = 0x8A;
Ptr->Len = 0x2B;
Ptr->ResType = 0;
- Ptr->GenFlag = 0;
+ Ptr->GenFlag = 0;
Ptr->SpecificFlag = 6;
Ptr->AddrSpaceGranularity = 64;
Ptr->AddrRangeMin = 0;
Ptr->AddrRangeMax = 0;
- Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
+ Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
Ptr->AddrLen = 0;
break;
};
-
+
Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
- }
+ }
}
-
- ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
+
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
-
- *Configuration = Buffer;
-
+
+ *Configuration = Buffer;
+
return EFI_SUCCESS;
}
-
+
List = List->ForwardLink;
}
-
+
return EFI_INVALID_PARAMETER;
}

@@ -1322,15 +1361,15 @@ GetProposedResources(
EFI_STATUS
EFIAPI
PreprocessController (
- IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
- IN EFI_HANDLE RootBridgeHandle,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
- IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
)
{
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
- LIST_ENTRY *List;
+ LIST_ENTRY *List;

HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
List = HostBridgeInstance->Head.ForwardLink;
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:10 UTC
Permalink
In this patch the code and the comments embedded in code are rewrapped to
79 columns, plus any trailing whitespace is stripped.

Cc: Ruiyu Ni <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
Reviewed-by: Ruiyu Ni <***@intel.com>
---

Notes:
v3:
- rewrap the driver under PcAtChipsetPkg

PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c | 213 +++++++++++---------
1 file changed, 123 insertions(+), 90 deletions(-)

diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c b/PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c
index a386130..5de28b1 100644
--- a/PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c
+++ b/PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c
@@ -22,7 +22,7 @@ typedef struct {

RESOURCE_CONFIGURATION Configuration = {
{{0x8A, 0x2B, 1, 0, 0, 0, 0, 0, 0, 0},
- {0x8A, 0x2B, 0, 0, 0, 32, 0, 0, 0, 0},
+ {0x8A, 0x2B, 0, 0, 0, 32, 0, 0, 0, 0},
{0x8A, 0x2B, 0, 0, 6, 32, 0, 0, 0, 0},
{0x8A, 0x2B, 0, 0, 0, 64, 0, 0, 0, 0},
{0x8A, 0x2B, 0, 0, 6, 64, 0, 0, 0, 0},
@@ -80,7 +80,7 @@ RESOURCE_CONFIGURATION Configuration = {
**/
EFI_STATUS
EFIAPI
-RootBridgeIoPollMem (
+RootBridgeIoPollMem (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 Address,
@@ -135,7 +135,7 @@ RootBridgeIoPollMem (
**/
EFI_STATUS
EFIAPI
-RootBridgeIoPollIo (
+RootBridgeIoPollIo (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 Address,
@@ -723,8 +723,8 @@ RootBridgeIoSetAttributes (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN UINT64 Attributes,
IN OUT UINT64 *ResourceBase,
- IN OUT UINT64 *ResourceLength
- );
+ IN OUT UINT64 *ResourceLength
+ );

/**
Retrieves the current resource settings of this PCI root bridge in the form
@@ -851,7 +851,7 @@ RootBridgeConstructor (
//
PrivateData->BusBase = ResAperture->BusBase;
PrivateData->BusLimit = ResAperture->BusLimit;
-
+
//
// Specific for this chipset
//
@@ -861,17 +861,20 @@ RootBridgeConstructor (
PrivateData->ResAllocNode[Index].Length = 0;
PrivateData->ResAllocNode[Index].Status = ResNone;
}
-
+
PrivateData->RootBridgeAttrib = Attri;
-
- PrivateData->Supports = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO | \
- EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO | \
- EFI_PCI_ATTRIBUTE_VGA_MEMORY | \
- EFI_PCI_ATTRIBUTE_VGA_IO_16 | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
+
+ PrivateData->Supports = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO |
+ EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |
+ EFI_PCI_ATTRIBUTE_ISA_IO_16 |
+ EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO |
+ EFI_PCI_ATTRIBUTE_VGA_MEMORY |
+ EFI_PCI_ATTRIBUTE_VGA_IO_16 |
+ EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
PrivateData->Attributes = PrivateData->Supports;

Protocol->ParentHandle = HostBridgeHandle;
-
+
Protocol->PollMem = RootBridgeIoPollMem;
Protocol->PollIo = RootBridgeIoPollIo;

@@ -901,7 +904,8 @@ RootBridgeConstructor (

Protocol->SegmentNumber = 0;

- Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **)&mMetronome);
+ Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL,
+ (VOID **)&mMetronome);
ASSERT_EFI_ERROR (Status);

return EFI_SUCCESS;
@@ -1001,18 +1005,18 @@ RootBridgeIoCheckParameter (
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);

//
- // Check to see if any address associated with this transfer exceeds the maximum
- // allowed address. The maximum address implied by the parameters passed in is
- // Address + Size * Count. If the following condition is met, then the transfer
- // is not supported.
+ // Check to see if any address associated with this transfer exceeds the
+ // maximum allowed address. The maximum address implied by the parameters
+ // passed in is Address + Size * Count. If the following condition is met,
+ // then the transfer is not supported.
//
// Address + Size * Count > Limit + 1
//
- // Since Limit can be the maximum integer value supported by the CPU and Count
- // can also be the maximum integer value supported by the CPU, this range
- // check must be adjusted to avoid all oveflow conditions.
- //
- // The following form of the range check is equivalent but assumes that
+ // Since Limit can be the maximum integer value supported by the CPU and
+ // Count can also be the maximum integer value supported by the CPU, this
+ // range check must be adjusted to avoid all oveflow conditions.
+ //
+ // The following form of the range check is equivalent but assumes that
// Limit is of the form (2^n - 1).
//
if (OperationType == IoOperation) {
@@ -1023,11 +1027,13 @@ RootBridgeIoCheckParameter (
Limit = PrivateData->MemLimit;
} else {
PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &Address;
- if (PciRbAddr->Bus < PrivateData->BusBase || PciRbAddr->Bus > PrivateData->BusLimit) {
+ if (PciRbAddr->Bus < PrivateData->BusBase ||
+ PciRbAddr->Bus > PrivateData->BusLimit) {
return EFI_INVALID_PARAMETER;
}

- if (PciRbAddr->Device > MAX_PCI_DEVICE_NUMBER || PciRbAddr->Function > MAX_PCI_FUNCTION_NUMBER) {
+ if (PciRbAddr->Device > MAX_PCI_DEVICE_NUMBER ||
+ PciRbAddr->Function > MAX_PCI_FUNCTION_NUMBER) {
return EFI_INVALID_PARAMETER;
}

@@ -1048,7 +1054,7 @@ RootBridgeIoCheckParameter (
if (Address > Limit) {
return EFI_UNSUPPORTED;
}
- } else {
+ } else {
MaxCount = RShiftU64 (Limit, Width);
if (MaxCount < (Count - 1)) {
return EFI_UNSUPPORTED;
@@ -1107,7 +1113,8 @@ RootBridgeIoMemRW (
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OperationWidth;
UINT8 *Uint8Buffer;

- Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address, Count, Buffer);
+ Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,
+ Count, Buffer);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -1115,7 +1122,9 @@ RootBridgeIoMemRW (
InStride = mInStride[Width];
OutStride = mOutStride[Width];
OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
- for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+ for (Uint8Buffer = Buffer;
+ Count > 0;
+ Address += InStride, Uint8Buffer += OutStride, Count--) {
if (Write) {
switch (OperationWidth) {
case EfiPciWidthUint8:
@@ -1162,7 +1171,7 @@ RootBridgeIoMemRW (
}
}
}
- return EFI_SUCCESS;
+ return EFI_SUCCESS;
}

/**
@@ -1212,7 +1221,8 @@ RootBridgeIoIoRW (
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OperationWidth;
UINT8 *Uint8Buffer;

- Status = RootBridgeIoCheckParameter (This, IoOperation, Width, Address, Count, Buffer);
+ Status = RootBridgeIoCheckParameter (This, IoOperation, Width, Address,
+ Count, Buffer);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -1265,7 +1275,9 @@ RootBridgeIoIoRW (
}
#endif

- for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+ for (Uint8Buffer = Buffer;
+ Count > 0;
+ Address += InStride, Uint8Buffer += OutStride, Count--) {
if (Write) {
switch (OperationWidth) {
case EfiPciWidthUint8:
@@ -1358,7 +1370,8 @@ RootBridgeIoPciRW (
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *PciRbAddr;
UINTN PcieRegAddr;

- Status = RootBridgeIoCheckParameter (This, PciOperation, Width, Address, Count, Buffer);
+ Status = RootBridgeIoCheckParameter (This, PciOperation, Width, Address,
+ Count, Buffer);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -1377,7 +1390,9 @@ RootBridgeIoPciRW (
InStride = mInStride[Width];
OutStride = mOutStride[Width];
OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
- for (Uint8Buffer = Buffer; Count > 0; PcieRegAddr += InStride, Uint8Buffer += OutStride, Count--) {
+ for (Uint8Buffer = Buffer;
+ Count > 0;
+ PcieRegAddr += InStride, Uint8Buffer += OutStride, Count--) {
if (Write) {
switch (OperationWidth) {
case EfiPciWidthUint8:
@@ -1468,7 +1483,7 @@ RootBridgeIoPciRW (
**/
EFI_STATUS
EFIAPI
-RootBridgeIoPollMem (
+RootBridgeIoPollMem (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 Address,
@@ -1496,40 +1511,42 @@ RootBridgeIoPollMem (
Status = This->Mem.Read (This, Width, Address, 1, Result);
if (EFI_ERROR (Status)) {
return Status;
- }
+ }
if ((*Result & Mask) == Value) {
return EFI_SUCCESS;
}

if (Delay == 0) {
return EFI_SUCCESS;
-
+
} else {

//
// Determine the proper # of metronome ticks to wait for polling the
- // location. The nuber of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
+ // location. The nuber of ticks is Roundup (Delay /
+ // mMetronome->TickPeriod)+1
// The "+1" to account for the possibility of the first tick being short
// because we started in the middle of a tick.
//
// BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome
// protocol definition is updated.
//
- NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod, &Remainder);
+ NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod,
+ &Remainder);
if (Remainder != 0) {
NumberOfTicks += 1;
}
NumberOfTicks += 1;
-
+
while (NumberOfTicks != 0) {

mMetronome->WaitForTick (mMetronome, 1);
-
+
Status = This->Mem.Read (This, Width, Address, 1, Result);
if (EFI_ERROR (Status)) {
return Status;
}
-
+
if ((*Result & Mask) == Value) {
return EFI_SUCCESS;
}
@@ -1584,7 +1601,7 @@ RootBridgeIoPollMem (
**/
EFI_STATUS
EFIAPI
-RootBridgeIoPollIo (
+RootBridgeIoPollIo (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 Address,
@@ -1609,41 +1626,43 @@ RootBridgeIoPollIo (
if ((UINT32)Width > EfiPciWidthUint64) {
return EFI_INVALID_PARAMETER;
}
-
+
Status = This->Io.Read (This, Width, Address, 1, Result);
if (EFI_ERROR (Status)) {
return Status;
- }
+ }
if ((*Result & Mask) == Value) {
return EFI_SUCCESS;
}

if (Delay == 0) {
return EFI_SUCCESS;
-
+
} else {

//
// Determine the proper # of metronome ticks to wait for polling the
- // location. The number of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
+ // location. The number of ticks is Roundup (Delay /
+ // mMetronome->TickPeriod)+1
// The "+1" to account for the possibility of the first tick being short
// because we started in the middle of a tick.
//
- NumberOfTicks = DivU64x32Remainder (Delay, (UINT32)mMetronome->TickPeriod, &Remainder);
+ NumberOfTicks = DivU64x32Remainder (Delay, (UINT32)mMetronome->TickPeriod,
+ &Remainder);
if (Remainder != 0) {
NumberOfTicks += 1;
}
NumberOfTicks += 1;
-
+
while (NumberOfTicks != 0) {

mMetronome->WaitForTick (mMetronome, 1);
-
+
Status = This->Io.Read (This, Width, Address, 1, Result);
if (EFI_ERROR (Status)) {
return Status;
}
-
+
if ((*Result & Mask) == Value) {
return EFI_SUCCESS;
}
@@ -1745,7 +1764,7 @@ RootBridgeIoMemWrite (
IN VOID *Buffer
)
{
- return RootBridgeIoMemRW (This, TRUE, Width, Address, Count, Buffer);
+ return RootBridgeIoMemRW (This, TRUE, Width, Address, Count, Buffer);
}

/**
@@ -1787,7 +1806,7 @@ RootBridgeIoIoRead (
OUT VOID *Buffer
)
{
- return RootBridgeIoIoRW (This, FALSE, Width, Address, Count, Buffer);
+ return RootBridgeIoIoRW (This, FALSE, Width, Address, Count, Buffer);
}

/**
@@ -1828,7 +1847,7 @@ RootBridgeIoIoWrite (
IN VOID *Buffer
)
{
- return RootBridgeIoIoRW (This, TRUE, Width, Address, Count, Buffer);
+ return RootBridgeIoIoRW (This, TRUE, Width, Address, Count, Buffer);
}

/**
@@ -1886,7 +1905,7 @@ RootBridgeIoCopyMem (

if ((UINT32)Width > EfiPciWidthUint64) {
return EFI_INVALID_PARAMETER;
- }
+ }

if (DestAddress == SrcAddress) {
return EFI_SUCCESS;
@@ -1895,7 +1914,8 @@ RootBridgeIoCopyMem (
Stride = (UINTN)(1 << Width);

Direction = TRUE;
- if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
+ if ((DestAddress > SrcAddress) &&
+ (DestAddress < (SrcAddress + Count * Stride))) {
Direction = FALSE;
SrcAddress = SrcAddress + (Count-1) * Stride;
DestAddress = DestAddress + (Count-1) * Stride;
@@ -2093,10 +2113,11 @@ RootBridgeIoMap (
EFI_PHYSICAL_ADDRESS PhysicalAddress;
MAP_INFO *MapInfo;

- if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {
+ if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL ||
+ Mapping == NULL) {
return EFI_INVALID_PARAMETER;
}
-
+
//
// Initialize the return values to their defaults
//
@@ -2119,10 +2140,11 @@ RootBridgeIoMap (

//
// Common Buffer operations can not be remapped. If the common buffer
- // if above 4GB, then it is not possible to generate a mapping, so return
+ // if above 4GB, then it is not possible to generate a mapping, so return
// an error.
//
- if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
+ if (Operation == EfiPciOperationBusMasterCommonBuffer ||
+ Operation == EfiPciOperationBusMasterCommonBuffer64) {
return EFI_UNSUPPORTED;
}

@@ -2131,8 +2153,8 @@ RootBridgeIoMap (
// called later.
//
Status = gBS->AllocatePool (
- EfiBootServicesData,
- sizeof(MAP_INFO),
+ EfiBootServicesData,
+ sizeof(MAP_INFO),
(VOID **)&MapInfo
);
if (EFI_ERROR (Status)) {
@@ -2158,8 +2180,8 @@ RootBridgeIoMap (
// Allocate a buffer below 4GB to map the transfer to.
//
Status = gBS->AllocatePages (
- AllocateMaxAddress,
- EfiBootServicesData,
+ AllocateMaxAddress,
+ EfiBootServicesData,
MapInfo->NumberOfPages,
&MapInfo->MappedHostAddress
);
@@ -2174,9 +2196,10 @@ RootBridgeIoMap (
// then copy the contents of the real buffer into the mapped buffer
// so the Bus Master can read the contents of the real buffer.
//
- if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
+ if (Operation == EfiPciOperationBusMasterRead ||
+ Operation == EfiPciOperationBusMasterRead64) {
CopyMem (
- (VOID *)(UINTN)MapInfo->MappedHostAddress,
+ (VOID *)(UINTN)MapInfo->MappedHostAddress,
(VOID *)(UINTN)MapInfo->HostAddress,
MapInfo->NumberOfBytes
);
@@ -2188,7 +2211,8 @@ RootBridgeIoMap (
*DeviceAddress = MapInfo->MappedHostAddress;
} else {
//
- // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress
+ // The transfer is below 4GB, so the DeviceAddress is simply the
+ // HostAddress
//
*DeviceAddress = PhysicalAddress;
}
@@ -2228,8 +2252,9 @@ RootBridgeIoUnmap (
MAP_INFO *MapInfo;

//
- // See if the Map() operation associated with this Unmap() required a mapping buffer.
- // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
+ // See if the Map() operation associated with this Unmap() required a mapping
+ // buffer. If a mapping buffer was not required, then this function simply
+ // returns EFI_SUCCESS.
//
if (Mapping != NULL) {
//
@@ -2242,9 +2267,10 @@ RootBridgeIoUnmap (
// then copy the contents of the mapped buffer into the real buffer
// so the processor can read the contents of the real buffer.
//
- if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {
+ if (MapInfo->Operation == EfiPciOperationBusMasterWrite ||
+ MapInfo->Operation == EfiPciOperationBusMasterWrite64) {
CopyMem (
- (VOID *)(UINTN)MapInfo->HostAddress,
+ (VOID *)(UINTN)MapInfo->HostAddress,
(VOID *)(UINTN)MapInfo->MappedHostAddress,
MapInfo->NumberOfBytes
);
@@ -2321,11 +2347,13 @@ RootBridgeIoAllocateBuffer (
if (HostAddress == NULL) {
return EFI_INVALID_PARAMETER;
}
-
+
//
- // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
+ // The only valid memory types are EfiBootServicesData and
+ // EfiRuntimeServicesData
//
- if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
+ if (MemoryType != EfiBootServicesData &&
+ MemoryType != EfiRuntimeServicesData) {
return EFI_INVALID_PARAMETER;
}

@@ -2334,7 +2362,8 @@ RootBridgeIoAllocateBuffer (
//
PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff);

- Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);
+ Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages,
+ &PhysicalAddress);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -2451,13 +2480,13 @@ RootBridgeIoGetAttributes (
// Set the return value for Supported and Attributes
//
if (Supported != NULL) {
- *Supported = PrivateData->Supports;
+ *Supported = PrivateData->Supports;
}

if (Attributes != NULL) {
*Attributes = PrivateData->Attributes;
}
-
+
return EFI_SUCCESS;
}

@@ -2510,23 +2539,23 @@ RootBridgeIoSetAttributes (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN UINT64 Attributes,
IN OUT UINT64 *ResourceBase,
- IN OUT UINT64 *ResourceLength
+ IN OUT UINT64 *ResourceLength
)
{
PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
-
+
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
-
+
if (Attributes != 0) {
if ((Attributes & (~(PrivateData->Supports))) != 0) {
return EFI_UNSUPPORTED;
}
}
-
+
//
// This is a generic driver for a PC-AT class system. It does not have any
- // chipset specific knowlegde, so none of the attributes can be set or
- // cleared. Any attempt to set attribute that are already set will succeed,
+ // chipset specific knowlegde, so none of the attributes can be set or
+ // cleared. Any attempt to set attribute that are already set will succeed,
// and any attempt to set an attribute that is not supported will fail.
//
if (Attributes & (~PrivateData->Attributes)) {
@@ -2578,16 +2607,20 @@ RootBridgeIoConfiguration (
UINTN Index;

PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
-
+
for (Index = 0; Index < TypeMax; Index++) {
if (PrivateData->ResAllocNode[Index].Status == ResAllocated) {
- Configuration.SpaceDesp[Index].AddrRangeMin = PrivateData->ResAllocNode[Index].Base;
- Configuration.SpaceDesp[Index].AddrRangeMax = PrivateData->ResAllocNode[Index].Base + PrivateData->ResAllocNode[Index].Length - 1;
- Configuration.SpaceDesp[Index].AddrLen = PrivateData->ResAllocNode[Index].Length;
- }
- }
-
- *Resources = &Configuration;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
+
+ Desc = &Configuration.SpaceDesp[Index];
+ Desc->AddrRangeMin = PrivateData->ResAllocNode[Index].Base;
+ Desc->AddrRangeMax = PrivateData->ResAllocNode[Index].Base +
+ PrivateData->ResAllocNode[Index].Length - 1;
+ Desc->AddrLen = PrivateData->ResAllocNode[Index].Length;
+ }
+ }
+
+ *Resources = &Configuration;
return EFI_SUCCESS;
}
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:13 UTC
Permalink
The ASSERT() in SetPciIntLine() assumes that Device 0 on "the" root bus
corresponds to the PCI host bridge (00:00). This used to be true, but
because we're going to have extra root buses (with nonzero bus numbers),
soon this assumption may no longer hold. Check for the zero root bus
number explicitly.

Cc: Jordan Justen <***@intel.com>
Cc: Gabriel Somlo <***@cmu.edu>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Acked-by: Gabriel Somlo <***@cmu.edu>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
---
OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
index fdae6b1..243db44 100644
--- a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
+++ b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
@@ -754,6 +754,7 @@ SetPciIntLine (
UINTN Idx;
UINT8 IrqLine;
EFI_STATUS Status;
+ UINT32 RootBusNumber;

Status = EFI_SUCCESS;

@@ -763,6 +764,13 @@ SetPciIntLine (
ASSERT (DevPathNode != NULL);
DevPath = DevPathNode;

+ RootBusNumber = 0;
+ if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&
+ DevicePathSubType (DevPathNode) == ACPI_DP &&
+ ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) {
+ RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;
+ }
+
//
// Compute index into PciHostIrqs[] table by walking
// the device path and adding up all device numbers
@@ -794,7 +802,7 @@ SetPciIntLine (
if (EFI_ERROR (Status)) {
return Status;
}
- if (RootSlot == 0) {
+ if (RootBusNumber == 0 && RootSlot == 0) {
DEBUG((
EFI_D_ERROR,
"%a: PCI host bridge (00:00.0) should have no interrupts!\n",
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:09 UTC
Permalink
Cc: Ruiyu Ni <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
Reviewed-by: Ruiyu Ni <***@intel.com>
---

Notes:
v3:
- rewrap the driver under PcAtChipsetPkg

PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c | 1841 ++++++++++++--------
1 file changed, 1133 insertions(+), 708 deletions(-)

diff --git a/PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c b/PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c
index 7986550..a386130 100644
--- a/PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c
+++ b/PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c
@@ -1,16 +1,16 @@
/** @file
PCI Root Bridge Io Protocol implementation

-Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials are
-licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
+ Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>

-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php

-**/
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/

#include "PciHostBridge.h"
#include "IoFifo.h"
@@ -35,33 +35,48 @@ RESOURCE_CONFIGURATION Configuration = {
//

/**
- Polls an address in memory mapped I/O space until an exit condition is met, or
- a timeout occurs.
-
- This function provides a standard way to poll a PCI memory location. A PCI memory read
- operation is performed at the PCI memory address specified by Address for the width specified
- by Width. The result of this PCI memory read operation is stored in Result. This PCI memory
- read operation is repeated until either a timeout of Delay 100 ns units has expired, or (Result &
- Mask) is equal to Value.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] Address The base address of the memory operations. The caller is
- responsible for aligning Address if required.
- @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask
- are ignored. The bits in the bytes below Width which are zero in
- Mask are ignored when polling the memory address.
- @param[in] Value The comparison value used for the polling exit criteria.
- @param[in] Delay The number of 100 ns units to poll. Note that timer available may
- be of poorer granularity.
- @param[out] Result Pointer to the last value read from the memory location.
-
- @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
- @retval EFI_INVALID_PARAMETER Width is invalid.
- @retval EFI_INVALID_PARAMETER Result is NULL.
- @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.
+ Polls an address in memory mapped I/O space until an exit condition is met,
+ or a timeout occurs.

+ This function provides a standard way to poll a PCI memory location. A PCI
+ memory read operation is performed at the PCI memory address specified by
+ Address for the width specified by Width. The result of this PCI memory read
+ operation is stored in Result. This PCI memory read operation is repeated
+ until either a timeout of Delay 100 ns units has expired, or (Result & Mask)
+ is equal to Value.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Width Signifies the width of the memory operations.
+
+ @param[in] Address The base address of the memory operations. The caller
+ is responsible for aligning Address if required.
+
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width
+ in Mask are ignored. The bits in the bytes below Width
+ which are zero in Mask are ignored when polling the
+ memory address.
+
+ @param[in] Value The comparison value used for the polling exit
+ criteria.
+
+ @param[in] Delay The number of 100 ns units to poll. Note that timer
+ available may be of poorer granularity.
+
+ @param[out] Result Pointer to the last value read from the memory
+ location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched
+ the poll exit criteria.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid.
+
+ @retval EFI_INVALID_PARAMETER Result is NULL.
+
+ @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.
**/
EFI_STATUS
EFIAPI
@@ -74,35 +89,49 @@ RootBridgeIoPollMem (
IN UINT64 Delay,
OUT UINT64 *Result
);
-
+
/**
- Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
- satisfied or after a defined duration.
-
- This function provides a standard way to poll a PCI I/O location. A PCI I/O read operation is
- performed at the PCI I/O address specified by Address for the width specified by Width.
- The result of this PCI I/O read operation is stored in Result. This PCI I/O read operation is
- repeated until either a timeout of Delay 100 ns units has expired, or (Result & Mask) is equal
- to Value.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Width Signifies the width of the I/O operations.
- @param[in] Address The base address of the I/O operations. The caller is responsible
- for aligning Address if required.
- @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask
- are ignored. The bits in the bytes below Width which are zero in
- Mask are ignored when polling the I/O address.
- @param[in] Value The comparison value used for the polling exit criteria.
- @param[in] Delay The number of 100 ns units to poll. Note that timer available may
- be of poorer granularity.
- @param[out] Result Pointer to the last value read from the memory location.
-
- @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
- @retval EFI_INVALID_PARAMETER Width is invalid.
- @retval EFI_INVALID_PARAMETER Result is NULL.
- @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.
+ Reads from the I/O space of a PCI Root Bridge. Returns when either the
+ polling exit criteria is satisfied or after a defined duration.

+ This function provides a standard way to poll a PCI I/O location. A PCI I/O
+ read operation is performed at the PCI I/O address specified by Address for
+ the width specified by Width. The result of this PCI I/O read operation is
+ stored in Result. This PCI I/O read operation is repeated until either a
+ timeout of Delay 100 ns units has expired, or (Result & Mask) is equal to
+ Value.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Width Signifies the width of the I/O operations.
+
+ @param[in] Address The base address of the I/O operations. The caller is
+ responsible for aligning Address if required.
+
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width in
+ Mask are ignored. The bits in the bytes below Width
+ which are zero in Mask are ignored when polling the I/O
+ address.
+
+ @param[in] Value The comparison value used for the polling exit criteria.
+
+
+ @param[in] Delay The number of 100 ns units to poll. Note that timer
+ available may be of poorer granularity.
+
+ @param[out] Result Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched
+ the poll exit criteria.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid.
+
+ @retval EFI_INVALID_PARAMETER Result is NULL.
+
+ @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.
**/
EFI_STATUS
EFIAPI
@@ -115,29 +144,40 @@ RootBridgeIoPollIo (
IN UINT64 Delay,
OUT UINT64 *Result
);
-
+
/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
- The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
- registers in the PCI root bridge memory space.
- The memory operations are carried out exactly as requested. The caller is responsible for satisfying
- any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Width Signifies the width of the memory operation.
- @param[in] Address The base address of the memory operation. The caller is
- responsible for aligning the Address if required.
- @param[in] Count The number of memory operations to perform. Bytes moved is
- Width size * Count, starting at Address.
- @param[out] Buffer For read operations, the destination buffer to store the results. For
- write operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
- @retval EFI_INVALID_PARAMETER Buffer is NULL.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Enables a PCI driver to access PCI controller registers in the PCI root
+ bridge memory space.

+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI
+ controller registers in the PCI root bridge memory space.
+ The memory operations are carried out exactly as requested. The caller is
+ responsible for satisfying any alignment and memory width restrictions that a
+ PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Width Signifies the width of the memory operation.
+
+ @param[in] Address The base address of the memory operation. The caller
+ is responsible for aligning the Address if required.
+
+ @param[in] Count The number of memory operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+
+ @param[out] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -150,26 +190,38 @@ RootBridgeIoMemRead (
);

/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
- The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
- registers in the PCI root bridge memory space.
- The memory operations are carried out exactly as requested. The caller is responsible for satisfying
- any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Width Signifies the width of the memory operation.
- @param[in] Address The base address of the memory operation. The caller is
- responsible for aligning the Address if required.
- @param[in] Count The number of memory operations to perform. Bytes moved is
- Width size * Count, starting at Address.
- @param[in] Buffer For read operations, the destination buffer to store the results. For
- write operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
- @retval EFI_INVALID_PARAMETER Buffer is NULL.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Enables a PCI driver to access PCI controller registers in the PCI root
+ bridge memory space.
+
+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI
+ controller registers in the PCI root bridge memory space.
+ The memory operations are carried out exactly as requested. The caller is
+ responsible for satisfying any alignment and memory width restrictions that a
+ PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Width Signifies the width of the memory operation.
+
+ @param[in] Address The base address of the memory operation. The caller
+ is responsible for aligning the Address if required.
+
+ @param[in] Count The number of memory operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+
+ @param[in] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -182,22 +234,33 @@ RootBridgeIoMemWrite (
);

/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] UserAddress The base address of the I/O operation. The caller is responsible for
- aligning the Address if required.
- @param[in] Count The number of I/O operations to perform. Bytes moved is Width
- size * Count, starting at Address.
- @param[out] UserBuffer For read operations, the destination buffer to store the results. For
- write operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
- @retval EFI_INVALID_PARAMETER Buffer is NULL.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Enables a PCI driver to access PCI controller registers in the PCI root
+ bridge I/O space.

+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Width Signifies the width of the memory operations.
+
+ @param[in] UserAddress The base address of the I/O operation. The caller is
+ responsible for aligning the Address if required.
+
+ @param[in] Count The number of I/O operations to perform. Bytes moved
+ is Width size * Count, starting at Address.
+
+ @param[out] UserBuffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ to write data from.
+
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -210,22 +273,33 @@ RootBridgeIoIoRead (
);

/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] UserAddress The base address of the I/O operation. The caller is responsible for
- aligning the Address if required.
- @param[in] Count The number of I/O operations to perform. Bytes moved is Width
- size * Count, starting at Address.
- @param[in] UserBuffer For read operations, the destination buffer to store the results. For
- write operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
- @retval EFI_INVALID_PARAMETER Buffer is NULL.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Enables a PCI driver to access PCI controller registers in the PCI root
+ bridge I/O space.

+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Width Signifies the width of the memory operations.
+
+ @param[in] UserAddress The base address of the I/O operation. The caller is
+ responsible for aligning the Address if required.
+
+ @param[in] Count The number of I/O operations to perform. Bytes moved
+ is Width size * Count, starting at Address.
+
+ @param[in] UserBuffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ to write data from.
+
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -238,28 +312,42 @@ RootBridgeIoIoWrite (
);

/**
- Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI
- root bridge memory space.
-
- The CopyMem() function enables a PCI driver to copy one region of PCI root bridge memory
- space to another region of PCI root bridge memory space. This is especially useful for video scroll
- operation on a memory mapped video buffer.
- The memory operations are carried out exactly as requested. The caller is responsible for satisfying
- any alignment and memory width restrictions that a PCI root bridge on a platform might require.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] DestAddress The destination address of the memory operation. The caller is
- responsible for aligning the DestAddress if required.
- @param[in] SrcAddress The source address of the memory operation. The caller is
- responsible for aligning the SrcAddress if required.
- @param[in] Count The number of memory operations to perform. Bytes moved is
- Width size * Count, starting at DestAddress and SrcAddress.
-
- @retval EFI_SUCCESS The data was copied from one memory region to another memory region.
- @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Enables a PCI driver to copy one region of PCI root bridge memory space to
+ another region of PCI root bridge memory space.

+ The CopyMem() function enables a PCI driver to copy one region of PCI root
+ bridge memory space to another region of PCI root bridge memory space. This
+ is especially useful for video scroll operation on a memory mapped video
+ buffer.
+ The memory operations are carried out exactly as requested. The caller is
+ responsible for satisfying any alignment and memory width restrictions that a
+ PCI root bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ instance.
+
+ @param[in] Width Signifies the width of the memory operations.
+
+ @param[in] DestAddress The destination address of the memory operation. The
+ caller is responsible for aligning the DestAddress if
+ required.
+
+ @param[in] SrcAddress The source address of the memory operation. The caller
+ is responsible for aligning the SrcAddress if
+ required.
+
+ @param[in] Count The number of memory operations to perform. Bytes
+ moved is Width size * Count, starting at DestAddress
+ and SrcAddress.
+
+
+ @retval EFI_SUCCESS The data was copied from one memory region
+ to another memory region.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -272,27 +360,40 @@ RootBridgeIoCopyMem (
);

/**
- Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
-
- The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
- registers for a PCI controller.
- The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
- any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
- require.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] Address The address within the PCI configuration space for the PCI controller.
- @param[in] Count The number of PCI configuration operations to perform. Bytes
- moved is Width size * Count, starting at Address.
- @param[out] Buffer For read operations, the destination buffer to store the results. For
- write operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
- @retval EFI_INVALID_PARAMETER Buffer is NULL.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Enables a PCI driver to access PCI controller registers in a PCI root
+ bridge's configuration space.

+ The Pci.Read() and Pci.Write() functions enable a driver to access PCI
+ configuration registers for a PCI controller.
+ The PCI Configuration operations are carried out exactly as requested. The
+ caller is responsible for any alignment and PCI configuration width issues
+ that a PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Width Signifies the width of the memory operations.
+
+ @param[in] Address The address within the PCI configuration space for the
+ PCI controller.
+
+ @param[in] Count The number of PCI configuration operations to perform.
+ Bytes moved is Width size * Count, starting at
+ Address.
+
+ @param[out] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ to write data from.
+
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -305,27 +406,40 @@ RootBridgeIoPciRead (
);

/**
- Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
-
- The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
- registers for a PCI controller.
- The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
- any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
- require.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] Address The address within the PCI configuration space for the PCI controller.
- @param[in] Count The number of PCI configuration operations to perform. Bytes
- moved is Width size * Count, starting at Address.
- @param[in] Buffer For read operations, the destination buffer to store the results. For
- write operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
- @retval EFI_INVALID_PARAMETER Buffer is NULL.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Enables a PCI driver to access PCI controller registers in a PCI root
+ bridge's configuration space.

+ The Pci.Read() and Pci.Write() functions enable a driver to access PCI
+ configuration registers for a PCI controller.
+ The PCI Configuration operations are carried out exactly as requested. The
+ caller is responsible for any alignment and PCI configuration width issues
+ that a PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Width Signifies the width of the memory operations.
+
+ @param[in] Address The address within the PCI configuration space for the
+ PCI controller.
+
+ @param[in] Count The number of PCI configuration operations to perform.
+ Bytes moved is Width size * Count, starting at
+ Address.
+
+ @param[in] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ to write data from.
+
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -338,30 +452,53 @@ RootBridgeIoPciWrite (
);

/**
- Provides the PCI controller-specific addresses required to access system memory from a
- DMA bus master.
-
- The Map() function provides the PCI controller specific addresses needed to access system
- memory. This function is used to map system memory for PCI bus master DMA accesses.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Operation Indicates if the bus master is going to read or write to system memory.
- @param[in] HostAddress The system memory address to map to the PCI controller.
- @param[in, out] NumberOfBytes On input the number of bytes to map. On output the number of bytes that were mapped.
- @param[out] DeviceAddress The resulting map address for the bus master PCI controller to use
- to access the system memory's HostAddress.
- @param[out] Mapping The value to pass to Unmap() when the bus master DMA operation is complete.
-
- @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
- @retval EFI_INVALID_PARAMETER Operation is invalid.
- @retval EFI_INVALID_PARAMETER HostAddress is NULL.
- @retval EFI_INVALID_PARAMETER NumberOfBytes is NULL.
- @retval EFI_INVALID_PARAMETER DeviceAddress is NULL.
- @retval EFI_INVALID_PARAMETER Mapping is NULL.
- @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
- @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Provides the PCI controller-specific addresses required to access system
+ memory from a DMA bus master.

+ The Map() function provides the PCI controller specific addresses needed to
+ access system memory. This function is used to map system memory for PCI bus
+ master DMA accesses.
+
+ @param[in] This A pointer to the
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Operation Indicates if the bus master is going to read
+ or write to system memory.
+
+ @param[in] HostAddress The system memory address to map to the PCI
+ controller.
+
+ @param[in, out] NumberOfBytes On input the number of bytes to map. On
+ output the number of bytes that were mapped.
+
+ @param[out] DeviceAddress The resulting map address for the bus master
+ PCI controller to use to access the system
+ memory's HostAddress.
+
+ @param[out] Mapping The value to pass to Unmap() when the bus
+ master DMA operation is complete.
+
+ @retval EFI_SUCCESS The range was mapped for the returned
+ NumberOfBytes.
+
+ @retval EFI_INVALID_PARAMETER Operation is invalid.
+
+ @retval EFI_INVALID_PARAMETER HostAddress is NULL.
+
+ @retval EFI_INVALID_PARAMETER NumberOfBytes is NULL.
+
+ @retval EFI_INVALID_PARAMETER DeviceAddress is NULL.
+
+ @retval EFI_INVALID_PARAMETER Mapping is NULL.
+
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common
+ buffer.
+
+ @retval EFI_DEVICE_ERROR The system hardware could not map the
+ requested address.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -375,20 +512,26 @@ RootBridgeIoMap (
);

/**
- Completes the Map() operation and releases any corresponding resources.
+ Completes the Map() operation and releases any corresponding resources.

- The Unmap() function completes the Map() operation and releases any corresponding resources.
- If the operation was an EfiPciOperationBusMasterWrite or
- EfiPciOperationBusMasterWrite64, the data is committed to the target system memory.
- Any resources used for the mapping are freed.
+ The Unmap() function completes the Map() operation and releases any
+ corresponding resources.
+ If the operation was an EfiPciOperationBusMasterWrite or
+ EfiPciOperationBusMasterWrite64, the data is committed to the target system
+ memory.
+ Any resources used for the mapping are freed.

- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Mapping The mapping value returned from Map().
-
- @retval EFI_SUCCESS The range was unmapped.
- @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
- @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.

+ @param[in] Mapping The mapping value returned from Map().
+
+ @retval EFI_SUCCESS The range was unmapped.
+
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by
+ Map().
+
+ @retval EFI_DEVICE_ERROR The data was not committed to the target
+ system memory.
**/
EFI_STATUS
EFIAPI
@@ -398,25 +541,39 @@ RootBridgeIoUnmap (
);

/**
- Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or
- EfiPciOperationBusMasterCommonBuffer64 mapping.
-
- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param Type This parameter is not used and must be ignored.
- @param MemoryType The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData.
- @param Pages The number of pages to allocate.
- @param HostAddress A pointer to store the base system memory address of the allocated range.
- @param Attributes The requested bit mask of attributes for the allocated range. Only
- the attributes EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_ATTRIBUTE_MEMORY_CACHED,
- and EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this function.
-
- @retval EFI_SUCCESS The requested memory pages were allocated.
- @retval EFI_INVALID_PARAMETER MemoryType is invalid.
- @retval EFI_INVALID_PARAMETER HostAddress is NULL.
- @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
- MEMORY_WRITE_COMBINE, MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
- @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
+ Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer
+ or EfiPciOperationBusMasterCommonBuffer64 mapping.

+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param Type This parameter is not used and must be ignored.
+
+ @param MemoryType The type of memory to allocate, EfiBootServicesData or
+ EfiRuntimeServicesData.
+
+ @param Pages The number of pages to allocate.
+
+ @param HostAddress A pointer to store the base system memory address of the
+ allocated range.
+
+ @param Attributes The requested bit mask of attributes for the allocated
+ range. Only the attributes
+ EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,
+ EFI_PCI_ATTRIBUTE_MEMORY_CACHED, and
+ EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this
+ function.
+
+ @retval EFI_SUCCESS The requested memory pages were allocated.
+
+ @retval EFI_INVALID_PARAMETER MemoryType is invalid.
+
+ @retval EFI_INVALID_PARAMETER HostAddress is NULL.
+
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal
+ attribute bits are MEMORY_WRITE_COMBINE,
+ MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
+
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
**/
EFI_STATUS
EFIAPI
@@ -430,18 +587,21 @@ RootBridgeIoAllocateBuffer (
);

/**
- Frees memory that was allocated with AllocateBuffer().
+ Frees memory that was allocated with AllocateBuffer().

- The FreeBuffer() function frees memory that was allocated with AllocateBuffer().
+ The FreeBuffer() function frees memory that was allocated with
+ AllocateBuffer().

- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param Pages The number of pages to free.
- @param HostAddress The base system memory address of the allocated range.
-
- @retval EFI_SUCCESS The requested memory pages were freed.
- @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
- was not allocated with AllocateBuffer().
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.

+ @param Pages The number of pages to free.
+
+ @param HostAddress The base system memory address of the allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were freed.
+
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and
+ Pages was not allocated with AllocateBuffer().
**/
EFI_STATUS
EFIAPI
@@ -452,23 +612,26 @@ RootBridgeIoFreeBuffer (
);

/**
- Flushes all PCI posted write transactions from a PCI host bridge to system memory.
+ Flushes all PCI posted write transactions from a PCI host bridge to system
+ memory.

- The Flush() function flushes any PCI posted write transactions from a PCI host bridge to system
- memory. Posted write transactions are generated by PCI bus masters when they perform write
- transactions to target addresses in system memory.
- This function does not flush posted write transactions from any PCI bridges. A PCI controller
- specific action must be taken to guarantee that the posted write transactions have been flushed from
- the PCI controller and from all the PCI bridges into the PCI host bridge. This is typically done with
- a PCI read transaction from the PCI controller prior to calling Flush().
+ The Flush() function flushes any PCI posted write transactions from a PCI
+ host bridge to system memory. Posted write transactions are generated by PCI
+ bus masters when they perform write transactions to target addresses in
+ system memory.
+ This function does not flush posted write transactions from any PCI bridges.
+ A PCI controller specific action must be taken to guarantee that the posted
+ write transactions have been flushed from the PCI controller and from all the
+ PCI bridges into the PCI host bridge. This is typically done with a PCI read
+ transaction from the PCI controller prior to calling Flush().

- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-
- @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host
- bridge to system memory.
- @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI
- host bridge due to a hardware error.
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.

+ @retval EFI_SUCCESS The PCI posted write transactions were flushed
+ from the PCI host bridge to system memory.
+
+ @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
@@ -477,24 +640,30 @@ RootBridgeIoFlush (
);

/**
- Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the
- attributes that a PCI root bridge is currently using.
+ Gets the attributes that a PCI root bridge supports setting with
+ SetAttributes(), and the attributes that a PCI root bridge is currently
+ using.

- The GetAttributes() function returns the mask of attributes that this PCI root bridge supports
- and the mask of attributes that the PCI root bridge is currently using.
+ The GetAttributes() function returns the mask of attributes that this PCI
+ root bridge supports and the mask of attributes that the PCI root bridge is
+ currently using.

- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param Supported A pointer to the mask of attributes that this PCI root bridge
- supports setting with SetAttributes().
- @param Attributes A pointer to the mask of attributes that this PCI root bridge is
- currently using.
-
- @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI root
- bridge supports is returned in Supports. If Attributes is
- not NULL, then the attributes that the PCI root bridge is currently
- using is returned in Attributes.
- @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.

+ @param Supported A pointer to the mask of attributes that this PCI root
+ bridge supports setting with SetAttributes().
+
+ @param Attributes A pointer to the mask of attributes that this PCI root
+ bridge is currently using.
+
+
+ @retval EFI_SUCCESS If Supports is not NULL, then the attributes
+ that the PCI root bridge supports is returned
+ in Supports. If Attributes is not NULL, then
+ the attributes that the PCI root bridge is
+ currently using is returned in Attributes.
+
+ @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
**/
EFI_STATUS
EFIAPI
@@ -505,33 +674,47 @@ RootBridgeIoGetAttributes (
);

/**
- Sets attributes for a resource range on a PCI root bridge.
-
- The SetAttributes() function sets the attributes specified in Attributes for the PCI root
- bridge on the resource range specified by ResourceBase and ResourceLength. Since the
- granularity of setting these attributes may vary from resource type to resource type, and from
- platform to platform, the actual resource range and the one passed in by the caller may differ. As a
- result, this function may set the attributes specified by Attributes on a larger resource range
- than the caller requested. The actual range is returned in ResourceBase and
- ResourceLength. The caller is responsible for verifying that the actual range for which the
- attributes were set is acceptable.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Attributes The mask of attributes to set. If the attribute bit
- MEMORY_WRITE_COMBINE, MEMORY_CACHED, or
- MEMORY_DISABLE is set, then the resource range is specified by
- ResourceBase and ResourceLength. If
- MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
- MEMORY_DISABLE are not set, then ResourceBase and
- ResourceLength are ignored, and may be NULL.
- @param[in, out] ResourceBase A pointer to the base address of the resource range to be modified
- by the attributes specified by Attributes.
- @param[in, out] ResourceLength A pointer to the length of the resource range to be modified by the
- attributes specified by Attributes.
-
- @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources.
- @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
- @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ Sets attributes for a resource range on a PCI root bridge.
+
+ The SetAttributes() function sets the attributes specified in Attributes for
+ the PCI root bridge on the resource range specified by ResourceBase and
+ ResourceLength. Since the granularity of setting these attributes may vary
+ from resource type to resource type, and from platform to platform, the
+ actual resource range and the one passed in by the caller may differ. As a
+ result, this function may set the attributes specified by Attributes on a
+ larger resource range than the caller requested. The actual range is returned
+ in ResourceBase and ResourceLength. The caller is responsible for verifying
+ that the actual range for which the attributes were set is acceptable.
+
+ @param[in] This A pointer to the
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Attributes The mask of attributes to set. If the
+ attribute bit MEMORY_WRITE_COMBINE,
+ MEMORY_CACHED, or MEMORY_DISABLE is set,
+ then the resource range is specified by
+ ResourceBase and ResourceLength. If
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
+ MEMORY_DISABLE are not set, then
+ ResourceBase and ResourceLength are ignored,
+ and may be NULL.
+
+ @param[in, out] ResourceBase A pointer to the base address of the
+ resource range to be modified by the
+ attributes specified by Attributes.
+
+ @param[in, out] ResourceLength A pointer to the length of the resource
+ range to be modified by the attributes
+ specified by Attributes.
+
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge
+ was returned in Resources.
+
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge
+ could not be retrieved.
+
+ @retval EFI_INVALID_PARAMETER Invalid pointer of
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL

**/
EFI_STATUS
@@ -544,27 +727,35 @@ RootBridgeIoSetAttributes (
);

/**
- Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0
- resource descriptors.
+ Retrieves the current resource settings of this PCI root bridge in the form
+ of a set of ACPI 2.0 resource descriptors.

- There are only two resource descriptor types from the ACPI Specification that may be used to
- describe the current resources allocated to a PCI root bridge. These are the QWORD Address
- Space Descriptor (ACPI 2.0 Section 6.4.3.5.1), and the End Tag (ACPI 2.0 Section 6.4.2.8). The
- QWORD Address Space Descriptor can describe memory, I/O, and bus number ranges for dynamic
- or fixed resources. The configuration of a PCI root bridge is described with one or more QWORD
- Address Space Descriptors followed by an End Tag.
+ There are only two resource descriptor types from the ACPI Specification that
+ may be used to describe the current resources allocated to a PCI root bridge.
+ These are the QWORD Address Space Descriptor (ACPI 2.0 Section 6.4.3.5.1),
+ and the End Tag (ACPI 2.0 Section 6.4.2.8). The QWORD Address Space
+ Descriptor can describe memory, I/O, and bus number ranges for dynamic or
+ fixed resources. The configuration of a PCI root bridge is described with one
+ or more QWORD Address Space Descriptors followed by an End Tag.

- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[out] Resources A pointer to the ACPI 2.0 resource descriptors that describe the
- current configuration of this PCI root bridge. The storage for the
- ACPI 2.0 resource descriptors is allocated by this function. The
- caller must treat the return buffer as read-only data, and the buffer
- must not be freed by the caller.
-
- @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources.
- @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
- @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.

+ @param[out] Resources A pointer to the ACPI 2.0 resource descriptors that
+ describe the current configuration of this PCI root
+ bridge. The storage for the ACPI 2.0 resource
+ descriptors is allocated by this function. The
+ caller must treat the return buffer as read-only
+ data, and the buffer must not be freed by the
+ caller.
+
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge
+ was returned in Resources.
+
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge
+ could not be retrieved.
+
+ @retval EFI_INVALID_PARAMETER Invalid pointer of
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
**/
EFI_STATUS
EFIAPI
@@ -615,16 +806,17 @@ UINT8 mOutStride[] = {
};

/**
-
Construct the Pci Root Bridge Io protocol

@param Protocol Point to protocol instance
+
@param HostBridgeHandle Handle of host bridge
+
@param Attri Attribute of host bridge
+
@param ResAperture ResourceAperture for host bridge

@retval EFI_SUCCESS Success to initialize the Pci Root Bridge.
-
**/
EFI_STATUS
RootBridgeConstructor (
@@ -718,28 +910,39 @@ RootBridgeConstructor (
/**
Check parameters for IO,MMIO,PCI read/write services of PCI Root Bridge IO.

- The I/O operations are carried out exactly as requested. The caller is responsible
- for satisfying any alignment and I/O width restrictions that a PI System on a
- platform might require. For example on some platforms, width requests of
- EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
- be handled by the driver.
-
+ The I/O operations are carried out exactly as requested. The caller is
+ responsible for satisfying any alignment and I/O width restrictions that a PI
+ System on a platform might require. For example on some platforms, width
+ requests of EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other
+ hand, will be handled by the driver.
+
@param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
@param[in] OperationType I/O operation type: IO/MMIO/PCI.
+
@param[in] Width Signifies the width of the I/O or Memory operation.
- @param[in] Address The base address of the I/O operation.
- @param[in] Count The number of I/O operations to perform. The number of
- bytes moved is Width size * Count, starting at Address.
- @param[in] Buffer For read operations, the destination buffer to store the results.
- For write operations, the source buffer from which to write data.

- @retval EFI_SUCCESS The parameters for this request pass the checks.
+ @param[in] Address The base address of the I/O operation.
+
+ @param[in] Count The number of I/O operations to perform. The number
+ of bytes moved is Width size * Count, starting at
+ Address.
+
+ @param[in] Buffer For read operations, the destination buffer to
+ store the results. For write operations, the source
+ buffer from which to write data.
+
+ @retval EFI_SUCCESS The parameters for this request pass the
+ checks.
+
@retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
+
@retval EFI_INVALID_PARAMETER Buffer is NULL.
+
@retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
- @retval EFI_UNSUPPORTED The address range specified by Address, Width,
+
+ @retval EFI_UNSUPPORTED The address range specified by Address, Width,
and Count is not valid for this PI system.
-
**/
EFI_STATUS
RootBridgeIoCheckParameter (
@@ -859,22 +1062,34 @@ RootBridgeIoCheckParameter (
}

/**
- Internal help function for read and write memory space.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Write Switch value for Read or Write.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] UserAddress The address within the PCI configuration space for the PCI controller.
- @param[in] Count The number of PCI configuration operations to perform. Bytes
- moved is Width size * Count, starting at Address.
- @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
- write operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
- @retval EFI_INVALID_PARAMETER Buffer is NULL.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Internal help function for read and write memory space.

+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Write Switch value for Read or Write.
+
+ @param[in] Width Signifies the width of the memory operations.
+
+ @param[in] UserAddress The address within the PCI configuration space for
+ the PCI controller.
+
+ @param[in] Count The number of PCI configuration operations to
+ perform. Bytes moved is Width size * Count,
+ starting at Address.
+
+ @param[in, out] UserBuffer For read operations, the destination buffer to
+ store the results. For write operations, the
+ source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
RootBridgeIoMemRW (
@@ -951,22 +1166,35 @@ RootBridgeIoMemRW (
}

/**
- Internal help function for read and write IO space.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Write Switch value for Read or Write.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] UserAddress The address within the PCI configuration space for the PCI controller.
- @param[in] Count The number of PCI configuration operations to perform. Bytes
- moved is Width size * Count, starting at Address.
- @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
- write operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
- @retval EFI_INVALID_PARAMETER Buffer is NULL.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Internal help function for read and write IO space.

+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Write Switch value for Read or Write.
+
+ @param[in] Width Signifies the width of the memory operations.
+
+ @param[in] UserAddress The address within the PCI configuration space for
+ the PCI controller.
+
+ @param[in] Count The number of PCI configuration operations to
+ perform. Bytes moved is Width size * Count,
+ starting at Address.
+
+ @param[in, out] UserBuffer For read operations, the destination buffer to
+ store the results. For write operations, the
+ source buffer to write data from.
+
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
RootBridgeIoIoRW (
@@ -1082,22 +1310,35 @@ RootBridgeIoIoRW (
}

/**
- Internal help function for read and write PCI configuration space.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Write Switch value for Read or Write.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] UserAddress The address within the PCI configuration space for the PCI controller.
- @param[in] Count The number of PCI configuration operations to perform. Bytes
- moved is Width size * Count, starting at Address.
- @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
- write operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
- @retval EFI_INVALID_PARAMETER Buffer is NULL.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Internal help function for read and write PCI configuration space.

+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Write Switch value for Read or Write.
+
+ @param[in] Width Signifies the width of the memory operations.
+
+ @param[in] UserAddress The address within the PCI configuration space for
+ the PCI controller.
+
+ @param[in] Count The number of PCI configuration operations to
+ perform. Bytes moved is Width size * Count,
+ starting at Address.
+
+ @param[in, out] UserBuffer For read operations, the destination buffer to
+ store the results. For write operations, the
+ source buffer to write data from.
+
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
RootBridgeIoPciRW (
@@ -1182,33 +1423,48 @@ RootBridgeIoPciRW (
}

/**
- Polls an address in memory mapped I/O space until an exit condition is met, or
- a timeout occurs.
-
- This function provides a standard way to poll a PCI memory location. A PCI memory read
- operation is performed at the PCI memory address specified by Address for the width specified
- by Width. The result of this PCI memory read operation is stored in Result. This PCI memory
- read operation is repeated until either a timeout of Delay 100 ns units has expired, or (Result &
- Mask) is equal to Value.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] Address The base address of the memory operations. The caller is
- responsible for aligning Address if required.
- @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask
- are ignored. The bits in the bytes below Width which are zero in
- Mask are ignored when polling the memory address.
- @param[in] Value The comparison value used for the polling exit criteria.
- @param[in] Delay The number of 100 ns units to poll. Note that timer available may
- be of poorer granularity.
- @param[out] Result Pointer to the last value read from the memory location.
-
- @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
- @retval EFI_INVALID_PARAMETER Width is invalid.
- @retval EFI_INVALID_PARAMETER Result is NULL.
- @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.
+ Polls an address in memory mapped I/O space until an exit condition is met,
+ or a timeout occurs.

+ This function provides a standard way to poll a PCI memory location. A PCI
+ memory read operation is performed at the PCI memory address specified by
+ Address for the width specified by Width. The result of this PCI memory read
+ operation is stored in Result. This PCI memory read operation is repeated
+ until either a timeout of Delay 100 ns units has expired, or (Result & Mask)
+ is equal to Value.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Width Signifies the width of the memory operations.
+
+ @param[in] Address The base address of the memory operations. The caller
+ is responsible for aligning Address if required.
+
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width
+ in Mask are ignored. The bits in the bytes below Width
+ which are zero in Mask are ignored when polling the
+ memory address.
+
+ @param[in] Value The comparison value used for the polling exit
+ criteria.
+
+ @param[in] Delay The number of 100 ns units to poll. Note that timer
+ available may be of poorer granularity.
+
+ @param[out] Result Pointer to the last value read from the memory
+ location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched
+ the poll exit criteria.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid.
+
+ @retval EFI_INVALID_PARAMETER Result is NULL.
+
+ @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.
**/
EFI_STATUS
EFIAPI
@@ -1283,35 +1539,48 @@ RootBridgeIoPollMem (
}
return EFI_TIMEOUT;
}
-
+
/**
- Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
- satisfied or after a defined duration.
-
- This function provides a standard way to poll a PCI I/O location. A PCI I/O read operation is
- performed at the PCI I/O address specified by Address for the width specified by Width.
- The result of this PCI I/O read operation is stored in Result. This PCI I/O read operation is
- repeated until either a timeout of Delay 100 ns units has expired, or (Result & Mask) is equal
- to Value.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Width Signifies the width of the I/O operations.
- @param[in] Address The base address of the I/O operations. The caller is responsible
- for aligning Address if required.
- @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask
- are ignored. The bits in the bytes below Width which are zero in
- Mask are ignored when polling the I/O address.
- @param[in] Value The comparison value used for the polling exit criteria.
- @param[in] Delay The number of 100 ns units to poll. Note that timer available may
- be of poorer granularity.
- @param[out] Result Pointer to the last value read from the memory location.
-
- @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
- @retval EFI_INVALID_PARAMETER Width is invalid.
- @retval EFI_INVALID_PARAMETER Result is NULL.
- @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.
+ Reads from the I/O space of a PCI Root Bridge. Returns when either the
+ polling exit criteria is satisfied or after a defined duration.

+ This function provides a standard way to poll a PCI I/O location. A PCI I/O
+ read operation is performed at the PCI I/O address specified by Address for
+ the width specified by Width.
+ The result of this PCI I/O read operation is stored in Result. This PCI I/O
+ read operation is repeated until either a timeout of Delay 100 ns units has
+ expired, or (Result & Mask) is equal to Value.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Width Signifies the width of the I/O operations.
+
+ @param[in] Address The base address of the I/O operations. The caller is
+ responsible for aligning Address if required.
+
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width in
+ Mask are ignored. The bits in the bytes below Width
+ which are zero in Mask are ignored when polling the I/O
+ address.
+
+ @param[in] Value The comparison value used for the polling exit criteria.
+
+ @param[in] Delay The number of 100 ns units to poll. Note that timer
+ available may be of poorer granularity.
+
+ @param[out] Result Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched
+ the poll exit criteria.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid.
+
+ @retval EFI_INVALID_PARAMETER Result is NULL.
+
+ @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.
**/
EFI_STATUS
EFIAPI
@@ -1386,27 +1655,38 @@ RootBridgeIoPollIo (
}

/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
- The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
- registers in the PCI root bridge memory space.
- The memory operations are carried out exactly as requested. The caller is responsible for satisfying
- any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Width Signifies the width of the memory operation.
- @param[in] Address The base address of the memory operation. The caller is
- responsible for aligning the Address if required.
- @param[in] Count The number of memory operations to perform. Bytes moved is
- Width size * Count, starting at Address.
- @param[out] Buffer For read operations, the destination buffer to store the results. For
- write operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
- @retval EFI_INVALID_PARAMETER Buffer is NULL.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Enables a PCI driver to access PCI controller registers in the PCI root
+ bridge memory space.

+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI
+ controller registers in the PCI root bridge memory space.
+ The memory operations are carried out exactly as requested. The caller is
+ responsible for satisfying any alignment and memory width restrictions that a
+ PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Width Signifies the width of the memory operation.
+
+ @param[in] Address The base address of the memory operation. The caller
+ is responsible for aligning the Address if required.
+
+ @param[in] Count The number of memory operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+
+ @param[out] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -1422,26 +1702,38 @@ RootBridgeIoMemRead (
}

/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
- The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
- registers in the PCI root bridge memory space.
- The memory operations are carried out exactly as requested. The caller is responsible for satisfying
- any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Width Signifies the width of the memory operation.
- @param[in] Address The base address of the memory operation. The caller is
- responsible for aligning the Address if required.
- @param[in] Count The number of memory operations to perform. Bytes moved is
- Width size * Count, starting at Address.
- @param[in] Buffer For read operations, the destination buffer to store the results. For
- write operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
- @retval EFI_INVALID_PARAMETER Buffer is NULL.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Enables a PCI driver to access PCI controller registers in the PCI root
+ bridge memory space.
+
+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI
+ controller registers in the PCI root bridge memory space.
+ The memory operations are carried out exactly as requested. The caller is
+ responsible for satisfying any alignment and memory width restrictions that a
+ PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Width Signifies the width of the memory operation.
+
+ @param[in] Address The base address of the memory operation. The caller
+ is responsible for aligning the Address if required.
+
+ @param[in] Count The number of memory operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+
+ @param[in] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -1457,22 +1749,33 @@ RootBridgeIoMemWrite (
}

/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] Address The base address of the I/O operation. The caller is responsible for
- aligning the Address if required.
- @param[in] Count The number of I/O operations to perform. Bytes moved is Width
- size * Count, starting at Address.
- @param[out] Buffer For read operations, the destination buffer to store the results. For
- write operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
- @retval EFI_INVALID_PARAMETER Buffer is NULL.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Enables a PCI driver to access PCI controller registers in the PCI root
+ bridge I/O space.

+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Width Signifies the width of the memory operations.
+
+ @param[in] Address The base address of the I/O operation. The caller is
+ responsible for aligning the Address if required.
+
+ @param[in] Count The number of I/O operations to perform. Bytes moved
+ is Width size * Count, starting at Address.
+
+ @param[out] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ to write data from.
+
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -1488,22 +1791,32 @@ RootBridgeIoIoRead (
}

/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] Address The base address of the I/O operation. The caller is responsible for
- aligning the Address if required.
- @param[in] Count The number of I/O operations to perform. Bytes moved is Width
- size * Count, starting at Address.
- @param[in] Buffer For read operations, the destination buffer to store the results. For
- write operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
- @retval EFI_INVALID_PARAMETER Buffer is NULL.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Enables a PCI driver to access PCI controller registers in the PCI root
+ bridge I/O space.

+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Width Signifies the width of the memory operations.
+
+ @param[in] Address The base address of the I/O operation. The caller is
+ responsible for aligning the Address if required.
+
+ @param[in] Count The number of I/O operations to perform. Bytes moved
+ is Width size * Count, starting at Address.
+
+ @param[in] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -1519,28 +1832,41 @@ RootBridgeIoIoWrite (
}

/**
- Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI
- root bridge memory space.
-
- The CopyMem() function enables a PCI driver to copy one region of PCI root bridge memory
- space to another region of PCI root bridge memory space. This is especially useful for video scroll
- operation on a memory mapped video buffer.
- The memory operations are carried out exactly as requested. The caller is responsible for satisfying
- any alignment and memory width restrictions that a PCI root bridge on a platform might require.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] DestAddress The destination address of the memory operation. The caller is
- responsible for aligning the DestAddress if required.
- @param[in] SrcAddress The source address of the memory operation. The caller is
- responsible for aligning the SrcAddress if required.
- @param[in] Count The number of memory operations to perform. Bytes moved is
- Width size * Count, starting at DestAddress and SrcAddress.
-
- @retval EFI_SUCCESS The data was copied from one memory region to another memory region.
- @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Enables a PCI driver to copy one region of PCI root bridge memory space to
+ another region of PCI root bridge memory space.

+ The CopyMem() function enables a PCI driver to copy one region of PCI root
+ bridge memory space to another region of PCI root bridge memory space. This
+ is especially useful for video scroll operation on a memory mapped video
+ buffer.
+ The memory operations are carried out exactly as requested. The caller is
+ responsible for satisfying any alignment and memory width restrictions that a
+ PCI root bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ instance.
+
+ @param[in] Width Signifies the width of the memory operations.
+
+ @param[in] DestAddress The destination address of the memory operation. The
+ caller is responsible for aligning the DestAddress if
+ required.
+
+ @param[in] SrcAddress The source address of the memory operation. The caller
+ is responsible for aligning the SrcAddress if
+ required.
+
+ @param[in] Count The number of memory operations to perform. Bytes
+ moved is Width size * Count, starting at DestAddress
+ and SrcAddress.
+
+ @retval EFI_SUCCESS The data was copied from one memory region
+ to another memory region.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -1608,27 +1934,39 @@ RootBridgeIoCopyMem (
}

/**
- Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
-
- The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
- registers for a PCI controller.
- The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
- any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
- require.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] Address The address within the PCI configuration space for the PCI controller.
- @param[in] Count The number of PCI configuration operations to perform. Bytes
- moved is Width size * Count, starting at Address.
- @param[out] Buffer For read operations, the destination buffer to store the results. For
- write operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
- @retval EFI_INVALID_PARAMETER Buffer is NULL.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Enables a PCI driver to access PCI controller registers in a PCI root
+ bridge's configuration space.

+ The Pci.Read() and Pci.Write() functions enable a driver to access PCI
+ configuration registers for a PCI controller.
+ The PCI Configuration operations are carried out exactly as requested. The
+ caller is responsible for any alignment and PCI configuration width issues
+ that a PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Width Signifies the width of the memory operations.
+
+ @param[in] Address The address within the PCI configuration space for the
+ PCI controller.
+
+ @param[in] Count The number of PCI configuration operations to perform.
+ Bytes moved is Width size * Count, starting at
+ Address.
+
+ @param[out] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -1644,27 +1982,39 @@ RootBridgeIoPciRead (
}

/**
- Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
-
- The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
- registers for a PCI controller.
- The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
- any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
- require.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] Address The address within the PCI configuration space for the PCI controller.
- @param[in] Count The number of PCI configuration operations to perform. Bytes
- moved is Width size * Count, starting at Address.
- @param[in] Buffer For read operations, the destination buffer to store the results. For
- write operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
- @retval EFI_INVALID_PARAMETER Buffer is NULL.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Enables a PCI driver to access PCI controller registers in a PCI root
+ bridge's configuration space.

+ The Pci.Read() and Pci.Write() functions enable a driver to access PCI
+ configuration registers for a PCI controller.
+ The PCI Configuration operations are carried out exactly as requested. The
+ caller is responsible for any alignment and PCI configuration width issues
+ that a PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Width Signifies the width of the memory operations.
+
+ @param[in] Address The address within the PCI configuration space for the
+ PCI controller.
+
+ @param[in] Count The number of PCI configuration operations to perform.
+ Bytes moved is Width size * Count, starting at
+ Address.
+
+ @param[in] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI
+ root bridge.
+
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -1680,30 +2030,53 @@ RootBridgeIoPciWrite (
}

/**
- Provides the PCI controller-specific addresses required to access system memory from a
- DMA bus master.
-
- The Map() function provides the PCI controller specific addresses needed to access system
- memory. This function is used to map system memory for PCI bus master DMA accesses.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Operation Indicates if the bus master is going to read or write to system memory.
- @param[in] HostAddress The system memory address to map to the PCI controller.
- @param[in, out] NumberOfBytes On input the number of bytes to map. On output the number of bytes that were mapped.
- @param[out] DeviceAddress The resulting map address for the bus master PCI controller to use
- to access the system memory's HostAddress.
- @param[out] Mapping The value to pass to Unmap() when the bus master DMA operation is complete.
-
- @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
- @retval EFI_INVALID_PARAMETER Operation is invalid.
- @retval EFI_INVALID_PARAMETER HostAddress is NULL.
- @retval EFI_INVALID_PARAMETER NumberOfBytes is NULL.
- @retval EFI_INVALID_PARAMETER DeviceAddress is NULL.
- @retval EFI_INVALID_PARAMETER Mapping is NULL.
- @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
- @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ Provides the PCI controller-specific addresses required to access system
+ memory from a DMA bus master.

+ The Map() function provides the PCI controller specific addresses needed to
+ access system memory. This function is used to map system memory for PCI bus
+ master DMA accesses.
+
+ @param[in] This A pointer to the
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Operation Indicates if the bus master is going to read
+ or write to system memory.
+
+ @param[in] HostAddress The system memory address to map to the PCI
+ controller.
+
+ @param[in, out] NumberOfBytes On input the number of bytes to map. On
+ output the number of bytes that were mapped.
+
+ @param[out] DeviceAddress The resulting map address for the bus master
+ PCI controller to use to access the system
+ memory's HostAddress.
+
+ @param[out] Mapping The value to pass to Unmap() when the bus
+ master DMA operation is complete.
+
+ @retval EFI_SUCCESS The range was mapped for the returned
+ NumberOfBytes.
+
+ @retval EFI_INVALID_PARAMETER Operation is invalid.
+
+ @retval EFI_INVALID_PARAMETER HostAddress is NULL.
+
+ @retval EFI_INVALID_PARAMETER NumberOfBytes is NULL.
+
+ @retval EFI_INVALID_PARAMETER DeviceAddress is NULL.
+
+ @retval EFI_INVALID_PARAMETER Mapping is NULL.
+
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common
+ buffer.
+
+ @retval EFI_DEVICE_ERROR The system hardware could not map the
+ requested address.
+
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
**/
EFI_STATUS
EFIAPI
@@ -1824,20 +2197,26 @@ RootBridgeIoMap (
}

/**
- Completes the Map() operation and releases any corresponding resources.
+ Completes the Map() operation and releases any corresponding resources.

- The Unmap() function completes the Map() operation and releases any corresponding resources.
- If the operation was an EfiPciOperationBusMasterWrite or
- EfiPciOperationBusMasterWrite64, the data is committed to the target system memory.
- Any resources used for the mapping are freed.
+ The Unmap() function completes the Map() operation and releases any
+ corresponding resources.
+ If the operation was an EfiPciOperationBusMasterWrite or
+ EfiPciOperationBusMasterWrite64, the data is committed to the target system
+ memory.
+ Any resources used for the mapping are freed.

- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Mapping The mapping value returned from Map().
-
- @retval EFI_SUCCESS The range was unmapped.
- @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
- @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.

+ @param[in] Mapping The mapping value returned from Map().
+
+ @retval EFI_SUCCESS The range was unmapped.
+
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by
+ Map().
+
+ @retval EFI_DEVICE_ERROR The data was not committed to the target
+ system memory.
**/
EFI_STATUS
EFIAPI
@@ -1881,25 +2260,39 @@ RootBridgeIoUnmap (
}

/**
- Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or
- EfiPciOperationBusMasterCommonBuffer64 mapping.
-
- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param Type This parameter is not used and must be ignored.
- @param MemoryType The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData.
- @param Pages The number of pages to allocate.
- @param HostAddress A pointer to store the base system memory address of the allocated range.
- @param Attributes The requested bit mask of attributes for the allocated range. Only
- the attributes EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_ATTRIBUTE_MEMORY_CACHED,
- and EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this function.
-
- @retval EFI_SUCCESS The requested memory pages were allocated.
- @retval EFI_INVALID_PARAMETER MemoryType is invalid.
- @retval EFI_INVALID_PARAMETER HostAddress is NULL.
- @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
- MEMORY_WRITE_COMBINE, MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
- @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
+ Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer
+ or EfiPciOperationBusMasterCommonBuffer64 mapping.

+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param Type This parameter is not used and must be ignored.
+
+ @param MemoryType The type of memory to allocate, EfiBootServicesData or
+ EfiRuntimeServicesData.
+
+ @param Pages The number of pages to allocate.
+
+ @param HostAddress A pointer to store the base system memory address of the
+ allocated range.
+
+ @param Attributes The requested bit mask of attributes for the allocated
+ range. Only the attributes
+ EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,
+ EFI_PCI_ATTRIBUTE_MEMORY_CACHED, and
+ EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this
+ function.
+
+ @retval EFI_SUCCESS The requested memory pages were allocated.
+
+ @retval EFI_INVALID_PARAMETER MemoryType is invalid.
+
+ @retval EFI_INVALID_PARAMETER HostAddress is NULL.
+
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal
+ attribute bits are MEMORY_WRITE_COMBINE,
+ MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
+
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
**/
EFI_STATUS
EFIAPI
@@ -1952,18 +2345,21 @@ RootBridgeIoAllocateBuffer (
}

/**
- Frees memory that was allocated with AllocateBuffer().
+ Frees memory that was allocated with AllocateBuffer().

- The FreeBuffer() function frees memory that was allocated with AllocateBuffer().
+ The FreeBuffer() function frees memory that was allocated with
+ AllocateBuffer().

- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param Pages The number of pages to free.
- @param HostAddress The base system memory address of the allocated range.
-
- @retval EFI_SUCCESS The requested memory pages were freed.
- @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
- was not allocated with AllocateBuffer().
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.

+ @param Pages The number of pages to free.
+
+ @param HostAddress The base system memory address of the allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were freed.
+
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and
+ Pages was not allocated with AllocateBuffer().
**/
EFI_STATUS
EFIAPI
@@ -1977,23 +2373,26 @@ RootBridgeIoFreeBuffer (
}

/**
- Flushes all PCI posted write transactions from a PCI host bridge to system memory.
+ Flushes all PCI posted write transactions from a PCI host bridge to system
+ memory.

- The Flush() function flushes any PCI posted write transactions from a PCI host bridge to system
- memory. Posted write transactions are generated by PCI bus masters when they perform write
- transactions to target addresses in system memory.
- This function does not flush posted write transactions from any PCI bridges. A PCI controller
- specific action must be taken to guarantee that the posted write transactions have been flushed from
- the PCI controller and from all the PCI bridges into the PCI host bridge. This is typically done with
- a PCI read transaction from the PCI controller prior to calling Flush().
+ The Flush() function flushes any PCI posted write transactions from a PCI
+ host bridge to system memory. Posted write transactions are generated by PCI
+ bus masters when they perform write transactions to target addresses in
+ system memory.
+ This function does not flush posted write transactions from any PCI bridges.
+ A PCI controller specific action must be taken to guarantee that the posted
+ write transactions have been flushed from the PCI controller and from all the
+ PCI bridges into the PCI host bridge. This is typically done with a PCI read
+ transaction from the PCI controller prior to calling Flush().

- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-
- @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host
- bridge to system memory.
- @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI
- host bridge due to a hardware error.
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.

+ @retval EFI_SUCCESS The PCI posted write transactions were flushed
+ from the PCI host bridge to system memory.
+
+ @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
@@ -2008,24 +2407,29 @@ RootBridgeIoFlush (
}

/**
- Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the
- attributes that a PCI root bridge is currently using.
+ Gets the attributes that a PCI root bridge supports setting with
+ SetAttributes(), and the attributes that a PCI root bridge is currently
+ using.

- The GetAttributes() function returns the mask of attributes that this PCI root bridge supports
- and the mask of attributes that the PCI root bridge is currently using.
+ The GetAttributes() function returns the mask of attributes that this PCI
+ root bridge supports and the mask of attributes that the PCI root bridge is
+ currently using.

- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param Supported A pointer to the mask of attributes that this PCI root bridge
- supports setting with SetAttributes().
- @param Attributes A pointer to the mask of attributes that this PCI root bridge is
- currently using.
-
- @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI root
- bridge supports is returned in Supports. If Attributes is
- not NULL, then the attributes that the PCI root bridge is currently
- using is returned in Attributes.
- @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.

+ @param Supported A pointer to the mask of attributes that this PCI root
+ bridge supports setting with SetAttributes().
+
+ @param Attributes A pointer to the mask of attributes that this PCI root
+ bridge is currently using.
+
+ @retval EFI_SUCCESS If Supports is not NULL, then the attributes
+ that the PCI root bridge supports is returned
+ in Supports. If Attributes is not NULL, then
+ the attributes that the PCI root bridge is
+ currently using is returned in Attributes.
+
+ @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
**/
EFI_STATUS
EFIAPI
@@ -2058,34 +2462,47 @@ RootBridgeIoGetAttributes (
}

/**
- Sets attributes for a resource range on a PCI root bridge.
-
- The SetAttributes() function sets the attributes specified in Attributes for the PCI root
- bridge on the resource range specified by ResourceBase and ResourceLength. Since the
- granularity of setting these attributes may vary from resource type to resource type, and from
- platform to platform, the actual resource range and the one passed in by the caller may differ. As a
- result, this function may set the attributes specified by Attributes on a larger resource range
- than the caller requested. The actual range is returned in ResourceBase and
- ResourceLength. The caller is responsible for verifying that the actual range for which the
- attributes were set is acceptable.
-
- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[in] Attributes The mask of attributes to set. If the attribute bit
- MEMORY_WRITE_COMBINE, MEMORY_CACHED, or
- MEMORY_DISABLE is set, then the resource range is specified by
- ResourceBase and ResourceLength. If
- MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
- MEMORY_DISABLE are not set, then ResourceBase and
- ResourceLength are ignored, and may be NULL.
- @param[in, out] ResourceBase A pointer to the base address of the resource range to be modified
- by the attributes specified by Attributes.
- @param[in, out] ResourceLength A pointer to the length of the resource range to be modified by the
- attributes specified by Attributes.
-
- @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources.
- @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
- @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ Sets attributes for a resource range on a PCI root bridge.

+ The SetAttributes() function sets the attributes specified in Attributes for
+ the PCI root bridge on the resource range specified by ResourceBase and
+ ResourceLength. Since the granularity of setting these attributes may vary
+ from resource type to resource type, and from platform to platform, the
+ actual resource range and the one passed in by the caller may differ. As a
+ result, this function may set the attributes specified by Attributes on a
+ larger resource range than the caller requested. The actual range is returned
+ in ResourceBase and ResourceLength. The caller is responsible for verifying
+ that the actual range for which the attributes were set is acceptable.
+
+ @param[in] This A pointer to the
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @param[in] Attributes The mask of attributes to set. If the
+ attribute bit MEMORY_WRITE_COMBINE,
+ MEMORY_CACHED, or MEMORY_DISABLE is set,
+ then the resource range is specified by
+ ResourceBase and ResourceLength. If
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
+ MEMORY_DISABLE are not set, then
+ ResourceBase and ResourceLength are ignored,
+ and may be NULL.
+
+ @param[in, out] ResourceBase A pointer to the base address of the
+ resource range to be modified by the
+ attributes specified by Attributes.
+
+ @param[in, out] ResourceLength A pointer to the length of the resource
+ range to be modified by the attributes
+ specified by Attributes.
+
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge
+ was returned in Resources.
+
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge
+ could not be retrieved.
+
+ @retval EFI_INVALID_PARAMETER Invalid pointer of
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
**/
EFI_STATUS
EFIAPI
@@ -2120,27 +2537,35 @@ RootBridgeIoSetAttributes (
}

/**
- Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0
- resource descriptors.
+ Retrieves the current resource settings of this PCI root bridge in the form
+ of a set of ACPI 2.0 resource descriptors.

- There are only two resource descriptor types from the ACPI Specification that may be used to
- describe the current resources allocated to a PCI root bridge. These are the QWORD Address
- Space Descriptor (ACPI 2.0 Section 6.4.3.5.1), and the End Tag (ACPI 2.0 Section 6.4.2.8). The
- QWORD Address Space Descriptor can describe memory, I/O, and bus number ranges for dynamic
- or fixed resources. The configuration of a PCI root bridge is described with one or more QWORD
- Address Space Descriptors followed by an End Tag.
+ There are only two resource descriptor types from the ACPI Specification that
+ may be used to describe the current resources allocated to a PCI root bridge.
+ These are the QWORD Address Space Descriptor (ACPI 2.0 Section 6.4.3.5.1),
+ and the End Tag (ACPI 2.0 Section 6.4.2.8). The QWORD Address Space
+ Descriptor can describe memory, I/O, and bus number ranges for dynamic or
+ fixed resources. The configuration of a PCI root bridge is described with one
+ or more QWORD Address Space Descriptors followed by an End Tag.

- @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param[out] Resources A pointer to the ACPI 2.0 resource descriptors that describe the
- current configuration of this PCI root bridge. The storage for the
- ACPI 2.0 resource descriptors is allocated by this function. The
- caller must treat the return buffer as read-only data, and the buffer
- must not be freed by the caller.
-
- @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources.
- @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
- @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.

+ @param[out] Resources A pointer to the ACPI 2.0 resource descriptors that
+ describe the current configuration of this PCI root
+ bridge. The storage for the ACPI 2.0 resource
+ descriptors is allocated by this function. The
+ caller must treat the return buffer as read-only
+ data, and the buffer must not be freed by the
+ caller.
+
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge
+ was returned in Resources.
+
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge
+ could not be retrieved.
+
+ @retval EFI_INVALID_PARAMETER Invalid pointer of
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
**/
EFI_STATUS
EFIAPI
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:16 UTC
Permalink
There is no need to store these constants in dedicated static storage
duration objects; we can simply open-code them, simplifying the code.

Cc: Jordan Justen <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
---
OvmfPkg/PciHostBridgeDxe/PciHostBridge.c | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
index 33cf119..9852909 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
@@ -18,16 +18,9 @@
#include "PciHostBridge.h"

//
-// Hard code: Root Bridge Number within the host bridge
-// Root Bridge's attribute
-// Root Bridge's device path
+// Hard code: Root Bridge's device path
// Root Bridge's resource aperture
//
-UINTN RootBridgeNumber = 1;
-
-UINT64 RootBridgeAttribute[1] = {
- EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
-};

EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[1] = {
{
@@ -117,7 +110,7 @@ InitializePciHostBridge (
return EFI_OUT_OF_RESOURCES;
}

- HostBridge->RootBridgeNumber = RootBridgeNumber;
+ HostBridge->RootBridgeNumber = 1;
InitializeListHead (&HostBridge->Head);

Status = gBS->InstallMultipleProtocolInterfaces (
@@ -148,7 +141,7 @@ InitializePciHostBridge (
RootBridgeConstructor (
&PrivateData->Io,
HostBridge->HostBridgeHandle,
- RootBridgeAttribute[Loop2],
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM,
&mResAperture[Loop2]
);
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:15 UTC
Permalink
The entry point function of this driver, InitializePciHostBridge(), and
the static storage duration objects it relies on, are speculatively
generic -- they nominally support more than one host bridges, but (a) the
code hardwires the number of host bridges as 1, (b) it's very unlikely
that we'd ever like to raise that number (especially by open-coding it).

So let's just remove the the nominal support, and simplify the code.

This patch is best viewed with "git show -b".

Cc: Jordan Justen <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
---
OvmfPkg/PciHostBridgeDxe/PciHostBridge.h | 6 -
OvmfPkg/PciHostBridgeDxe/PciHostBridge.c | 134 ++++++++++----------
2 files changed, 65 insertions(+), 75 deletions(-)

diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
index f475eb7..28e0cd0 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
@@ -37,12 +37,6 @@
#include <Library/IoLib.h>
#include <Library/PciLib.h>

-//
-// Hard code the host bridge number in the platform.
-// In this chipset, there is only one host bridge.
-//
-#define HOST_BRIDGE_NUMBER 1
-
#define MAX_PCI_DEVICE_NUMBER 31
#define MAX_PCI_FUNCTION_NUMBER 7
#define MAX_PCI_REG_ADDRESS 0xFF
diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
index aa02641..33cf119 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
@@ -2,6 +2,7 @@
Provides the basic interfaces to abstract a PCI Host Bridge Resource
Allocation

+ Copyright (C) 2015, Red Hat, Inc.
Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>

This program and the accompanying materials are licensed and made available
@@ -22,42 +23,40 @@
// Root Bridge's device path
// Root Bridge's resource aperture
//
-UINTN RootBridgeNumber[1] = { 1 };
+UINTN RootBridgeNumber = 1;

-UINT64 RootBridgeAttribute[1][1] = {
- { EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM }
+UINT64 RootBridgeAttribute[1] = {
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
};

-EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[1][1] = {
+EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[1] = {
{
{
{
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
{
- ACPI_DEVICE_PATH,
- ACPI_DP,
- {
- (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
- (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
- }
- },
- EISA_PNP_ID(0x0A03),
- 0
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
},
+ EISA_PNP_ID(0x0A03),
+ 0
+ },

+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
{
- END_DEVICE_PATH_TYPE,
- END_ENTIRE_DEVICE_PATH_SUBTYPE,
- {
- END_DEVICE_PATH_LENGTH,
- 0
- }
+ END_DEVICE_PATH_LENGTH,
+ 0
}
}
}
};

-PCI_ROOT_BRIDGE_RESOURCE_APERTURE mResAperture[1][1] = {
- {{0, 0xff, 0x80000000, 0xffffffff, 0, 0xffff}}
+PCI_ROOT_BRIDGE_RESOURCE_APERTURE mResAperture[1] = {
+ {0, 0xff, 0x80000000, 0xffffffff, 0, 0xffff}
};

EFI_HANDLE mDriverImageHandle;
@@ -103,7 +102,6 @@ InitializePciHostBridge (
)
{
EFI_STATUS Status;
- UINTN Loop1;
UINTN Loop2;
PCI_HOST_BRIDGE_INSTANCE *HostBridge;
PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
@@ -113,63 +111,61 @@ InitializePciHostBridge (
//
// Create Host Bridge Device Handle
//
- for (Loop1 = 0; Loop1 < HOST_BRIDGE_NUMBER; Loop1++) {
- HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE),
- &mPciHostBridgeInstanceTemplate);
- if (HostBridge == NULL) {
+ HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE),
+ &mPciHostBridgeInstanceTemplate);
+ if (HostBridge == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HostBridge->RootBridgeNumber = RootBridgeNumber;
+ InitializeListHead (&HostBridge->Head);
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &HostBridge->HostBridgeHandle,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid,
+ &HostBridge->ResAlloc,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (HostBridge);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Create Root Bridge Device Handle in this Host Bridge
+ //
+
+ for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) {
+ PrivateData = AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE));
+ if (PrivateData == NULL) {
return EFI_OUT_OF_RESOURCES;
}

- HostBridge->RootBridgeNumber = RootBridgeNumber[Loop1];
- InitializeListHead (&HostBridge->Head);
+ PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
+ PrivateData->DevicePath =
+ (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Loop2];

- Status = gBS->InstallMultipleProtocolInterfaces (
- &HostBridge->HostBridgeHandle,
- &gEfiPciHostBridgeResourceAllocationProtocolGuid,
- &HostBridge->ResAlloc,
+ RootBridgeConstructor (
+ &PrivateData->Io,
+ HostBridge->HostBridgeHandle,
+ RootBridgeAttribute[Loop2],
+ &mResAperture[Loop2]
+ );
+
+ Status = gBS->InstallMultipleProtocolInterfaces(
+ &PrivateData->Handle,
+ &gEfiDevicePathProtocolGuid,
+ PrivateData->DevicePath,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ &PrivateData->Io,
NULL
);
if (EFI_ERROR (Status)) {
- FreePool (HostBridge);
+ FreePool(PrivateData);
return EFI_DEVICE_ERROR;
}

- //
- // Create Root Bridge Device Handle in this Host Bridge
- //
-
- for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) {
- PrivateData = AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE));
- if (PrivateData == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
- PrivateData->DevicePath =
- (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Loop1][Loop2];
-
- RootBridgeConstructor (
- &PrivateData->Io,
- HostBridge->HostBridgeHandle,
- RootBridgeAttribute[Loop1][Loop2],
- &mResAperture[Loop1][Loop2]
- );
-
- Status = gBS->InstallMultipleProtocolInterfaces(
- &PrivateData->Handle,
- &gEfiDevicePathProtocolGuid,
- PrivateData->DevicePath,
- &gEfiPciRootBridgeIoProtocolGuid,
- &PrivateData->Io,
- NULL
- );
- if (EFI_ERROR (Status)) {
- FreePool(PrivateData);
- return EFI_DEVICE_ERROR;
- }
-
- InsertTailList (&HostBridge->Head, &PrivateData->Link);
- }
+ InsertTailList (&HostBridge->Head, &PrivateData->Link);
}

return EFI_SUCCESS;
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:14 UTC
Permalink
Currently we only connect the root bus with bus number 0, by device path.
Soon we will possibly have several extra root buses, so connect all root
buses up-front (bus number zero and otherwise), by protocol GUID.

Cc: Jordan Justen <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
---
OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf | 2 +-
OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h | 25 +--------
OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c | 53 ++++++--------------
OvmfPkg/Library/PlatformBdsLib/PlatformData.c | 13 -----
4 files changed, 18 insertions(+), 75 deletions(-)

diff --git a/OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf b/OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf
index 5a28d78..ce29720 100644
--- a/OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf
+++ b/OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf
@@ -64,4 +64,4 @@ [Pcd.IA32, Pcd.X64]

[Protocols]
gEfiDecompressProtocolGuid
-
+ gEfiPciRootBridgeIoProtocolGuid
diff --git a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h
index 7006fb3..e3e950e 100644
--- a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h
+++ b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h
@@ -52,6 +52,7 @@ Abstract:
#include <Protocol/PciIo.h>
#include <Protocol/FirmwareVolume2.h>
#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/PciRootBridgeIo.h>

#include <Guid/Acpi.h>
#include <Guid/SmBios.h>
@@ -64,7 +65,6 @@ Abstract:
extern BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[];
extern EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[];
extern EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[];
-extern EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges[];
extern ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode;
extern ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode;
extern UART_DEVICE_PATH gUartDeviceNode;
@@ -107,9 +107,6 @@ extern VENDOR_DEVICE_PATH gTerminalTypeDeviceNode;
0 \
}

-#define gPciRootBridge \
- PNPID_DEVICE_PATH_NODE(0x0A03)
-
#define gPciIsaBridge \
PCI_DEVICE_PATH_NODE(0, 0x1f)

@@ -152,16 +149,6 @@ extern VENDOR_DEVICE_PATH gTerminalTypeDeviceNode;
DEVICE_PATH_MESSAGING_PC_ANSI \
}

-#define gEndEntire \
- { \
- END_DEVICE_PATH_TYPE, \
- END_ENTIRE_DEVICE_PATH_SUBTYPE, \
- { \
- END_DEVICE_PATH_LENGTH, \
- 0 \
- } \
- }
-
#define PCI_CLASS_SCC 0x07
#define PCI_SUBCLASS_SERIAL 0x00
#define PCI_IF_16550 0x02
@@ -172,14 +159,6 @@ extern VENDOR_DEVICE_PATH gTerminalTypeDeviceNode;

#define IS_PCI_ISA_PDECODE(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)

-//
-// Platform Root Bridge
-//
-typedef struct {
- ACPI_HID_DEVICE_PATH PciRootBridge;
- EFI_DEVICE_PATH_PROTOCOL End;
-} PLATFORM_ROOT_BRIDGE_DEVICE_PATH;
-
typedef struct {
ACPI_HID_DEVICE_PATH PciRootBridge;
PCI_DEVICE_PATH IsaBridge;
@@ -223,8 +202,6 @@ typedef struct {
EFI_DEVICE_PATH_PROTOCOL End;
} USB_CLASS_FORMAT_DEVICE_PATH;

-extern PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0;
-
//
// Platform BDS Functions
//
diff --git a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
index 243db44..de13c6b 100644
--- a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
+++ b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
@@ -116,49 +116,27 @@ Returns:


EFI_STATUS
+EFIAPI
ConnectRootBridge (
- VOID
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Instance,
+ IN VOID *Context
)
-/*++
-
-Routine Description:
-
- Connect RootBridge
-
-Arguments:
-
- None.
-
-Returns:
-
- EFI_SUCCESS - Connect RootBridge successfully.
- EFI_STATUS - Connect RootBridge fail.
-
---*/
{
- EFI_STATUS Status;
- EFI_HANDLE RootHandle;
+ EFI_STATUS Status;

//
- // Make all the PCI_IO protocols on PCI Seg 0 show up
+ // Make the PCI bus driver connect the root bridge, non-recursively. This
+ // will produce a number of child handles with PciIo on them.
//
- BdsLibConnectDevicePath (gPlatformRootBridges[0]);
-
- Status = gBS->LocateDevicePath (
- &gEfiDevicePathProtocolGuid,
- &gPlatformRootBridges[0],
- &RootHandle
+ Status = gBS->ConnectController (
+ RootBridgeHandle, // ControllerHandle
+ NULL, // DriverImageHandle
+ NULL, // RemainingDevicePath -- produce all
+ // children
+ FALSE // Recursive
);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- return EFI_SUCCESS;
+ return Status;
}


@@ -1222,7 +1200,8 @@ Returns:

DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));

- ConnectRootBridge ();
+ VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid,
+ ConnectRootBridge, NULL);

if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {
DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "
diff --git a/OvmfPkg/Library/PlatformBdsLib/PlatformData.c b/OvmfPkg/Library/PlatformBdsLib/PlatformData.c
index 1a30531..f69c1a8 100644
--- a/OvmfPkg/Library/PlatformBdsLib/PlatformData.c
+++ b/OvmfPkg/Library/PlatformBdsLib/PlatformData.c
@@ -26,19 +26,6 @@ UART_DEVICE_PATH gUartDeviceNode = gUart;
VENDOR_DEVICE_PATH gTerminalTypeDeviceNode = gPcAnsiTerminal;

//
-// Predefined platform root bridge
-//
-PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0 = {
- gPciRootBridge,
- gEndEntire
-};
-
-EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges[] = {
- (EFI_DEVICE_PATH_PROTOCOL *) &gPlatformRootBridge0,
- NULL
-};
-
-//
// Platform specific keyboard device path
//
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:17 UTC
Permalink
Currently we define a device path for each root bridge statically (for all
one of them). Since we'll want to create a dynamic number of root bridges,
replace the static device paths with a common template, embed the actual
device path into the private root bridge structure, and distinguish the
device paths from each other in the UID field (as required by ACPI).

This patch is best viewed with "git show -b".

Cc: Jordan Justen <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
---
OvmfPkg/PciHostBridgeDxe/PciHostBridge.h | 3 +-
OvmfPkg/PciHostBridgeDxe/PciHostBridge.c | 49 ++++++++++----------
2 files changed, 27 insertions(+), 25 deletions(-)

diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
index 28e0cd0..05b8cec 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
@@ -1,6 +1,7 @@
/** @file
The Header file of the Pci Host Bridge Driver

+ Copyright (C) 2015, Red Hat, Inc.
Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>

This program and the accompanying materials are licensed and made available
@@ -605,7 +606,7 @@ typedef struct {
UINT64 MemLimit;
UINT64 IoLimit;

- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_PCI_ROOT_BRIDGE_DEVICE_PATH DevicePath;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;

} PCI_ROOT_BRIDGE_INSTANCE;
diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
index 9852909..c2277bf 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
@@ -17,37 +17,36 @@

#include "PciHostBridge.h"

-//
-// Hard code: Root Bridge's device path
-// Root Bridge's resource aperture
-//
-
-EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[1] = {
+STATIC
+CONST
+EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
{
{
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
{
- ACPI_DEVICE_PATH,
- ACPI_DP,
- {
- (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
- (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
- }
- },
- EISA_PNP_ID(0x0A03),
- 0
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
},
+ EISA_PNP_ID(0x0A03), // HID
+ 0 // UID
+ },

+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
{
- END_DEVICE_PATH_TYPE,
- END_ENTIRE_DEVICE_PATH_SUBTYPE,
- {
- END_DEVICE_PATH_LENGTH,
- 0
- }
+ END_DEVICE_PATH_LENGTH,
+ 0
}
}
};

+//
+// Hard code: Root Bridge's resource aperture
+//
+
PCI_ROOT_BRIDGE_RESOURCE_APERTURE mResAperture[1] = {
{0, 0xff, 0x80000000, 0xffffffff, 0, 0xffff}
};
@@ -135,8 +134,10 @@ InitializePciHostBridge (
}

PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
- PrivateData->DevicePath =
- (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Loop2];
+
+ CopyMem (&PrivateData->DevicePath, &mRootBridgeDevicePathTemplate,
+ sizeof mRootBridgeDevicePathTemplate);
+ PrivateData->DevicePath.AcpiDevicePath.UID = Loop2;

RootBridgeConstructor (
&PrivateData->Io,
@@ -148,7 +149,7 @@ InitializePciHostBridge (
Status = gBS->InstallMultipleProtocolInterfaces(
&PrivateData->Handle,
&gEfiDevicePathProtocolGuid,
- PrivateData->DevicePath,
+ &PrivateData->DevicePath,
&gEfiPciRootBridgeIoProtocolGuid,
&PrivateData->Io,
NULL
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:20 UTC
Permalink
On output, the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.Configuration() function
produces a pointer to a buffer of ACPI 2.0 resource descriptors:

Resources A pointer to the ACPI 2.0 resource descriptors that describe
the current configuration of this PCI root bridge. The
storage for the ACPI 2.0 resource descriptors is allocated by
this function. The caller must treat the return buffer as
read-only data, and the buffer must not be freed by the
caller.

PciHostBridgeDxe currently provides this buffer in a structure with static
storage duration. If multiple root bridges existed in parallel, the
pointers returned by their Configuration() methods would point to the same
static storage. A later Configuration() call would overwrite the storage
pointed out by an earlier Configuration() call (which was possibly made
for a different, but still alive, root bridge.)

Fix this problem by embedding the configuration buffer in
PCI_ROOT_BRIDGE_INSTANCE.

While we're at it, correct some typos (Desp -> Desc), spell out a missing
pack(1) pragma, and improve formatting.

Cc: Jordan Justen <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
---
OvmfPkg/PciHostBridgeDxe/PciHostBridge.h | 8 +++++
OvmfPkg/PciHostBridgeDxe/PciRootBridgeIo.c | 32 +++++++++++---------
2 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
index 05b8cec..d2c28bc 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
@@ -581,6 +581,13 @@ typedef struct {
RES_STATUS Status;
} PCI_RES_NODE;

+#pragma pack(1)
+typedef struct {
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR SpaceDesc[TypeMax];
+ EFI_ACPI_END_TAG_DESCRIPTOR EndDesc;
+} RESOURCE_CONFIGURATION;
+#pragma pack()
+
#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32('e', '2', 'p', 'b')

typedef struct {
@@ -609,6 +616,7 @@ typedef struct {
EFI_PCI_ROOT_BRIDGE_DEVICE_PATH DevicePath;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;

+ RESOURCE_CONFIGURATION ConfigBuffer;
} PCI_ROOT_BRIDGE_INSTANCE;


diff --git a/OvmfPkg/PciHostBridgeDxe/PciRootBridgeIo.c b/OvmfPkg/PciHostBridgeDxe/PciRootBridgeIo.c
index 5de28b1..c61fd1d 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciRootBridgeIo.c
+++ b/OvmfPkg/PciHostBridgeDxe/PciRootBridgeIo.c
@@ -1,6 +1,7 @@
/** @file
PCI Root Bridge Io Protocol implementation

+ Copyright (C) 2015, Red Hat, Inc.
Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>

This program and the accompanying materials are licensed and made available
@@ -15,19 +16,18 @@
#include "PciHostBridge.h"
#include "IoFifo.h"

-typedef struct {
- EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR SpaceDesp[TypeMax];
- EFI_ACPI_END_TAG_DESCRIPTOR EndDesp;
-} RESOURCE_CONFIGURATION;
-
-RESOURCE_CONFIGURATION Configuration = {
- {{0x8A, 0x2B, 1, 0, 0, 0, 0, 0, 0, 0},
- {0x8A, 0x2B, 0, 0, 0, 32, 0, 0, 0, 0},
- {0x8A, 0x2B, 0, 0, 6, 32, 0, 0, 0, 0},
- {0x8A, 0x2B, 0, 0, 0, 64, 0, 0, 0, 0},
- {0x8A, 0x2B, 0, 0, 6, 64, 0, 0, 0, 0},
- {0x8A, 0x2B, 2, 0, 0, 0, 0, 0, 0, 0}},
- {0x79, 0}
+STATIC
+CONST
+RESOURCE_CONFIGURATION mConfigurationTemplate = {
+ {
+ { 0x8A, 0x2B, 1, 0, 0, 0, 0, 0, 0, 0 }, // SpaceDesc[TypeIo]
+ { 0x8A, 0x2B, 0, 0, 0, 32, 0, 0, 0, 0 }, // SpaceDesc[TypeMem32]
+ { 0x8A, 0x2B, 0, 0, 6, 32, 0, 0, 0, 0 }, // SpaceDesc[TypePMem32]
+ { 0x8A, 0x2B, 0, 0, 0, 64, 0, 0, 0, 0 }, // SpaceDesc[TypeMem64]
+ { 0x8A, 0x2B, 0, 0, 6, 64, 0, 0, 0, 0 }, // SpaceDesc[TypePMem64]
+ { 0x8A, 0x2B, 2, 0, 0, 0, 0, 0, 0, 0 } // SpaceDesc[TypeBus]
+ },
+ { 0x79, 0 } // EndDesc
};

//
@@ -2607,12 +2607,14 @@ RootBridgeIoConfiguration (
UINTN Index;

PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+ CopyMem (&PrivateData->ConfigBuffer, &mConfigurationTemplate,
+ sizeof mConfigurationTemplate);

for (Index = 0; Index < TypeMax; Index++) {
if (PrivateData->ResAllocNode[Index].Status == ResAllocated) {
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;

- Desc = &Configuration.SpaceDesp[Index];
+ Desc = &PrivateData->ConfigBuffer.SpaceDesc[Index];
Desc->AddrRangeMin = PrivateData->ResAllocNode[Index].Base;
Desc->AddrRangeMax = PrivateData->ResAllocNode[Index].Base +
PrivateData->ResAllocNode[Index].Length - 1;
@@ -2620,7 +2622,7 @@ RootBridgeIoConfiguration (
}
}

- *Resources = &Configuration;
+ *Resources = &PrivateData->ConfigBuffer;
return EFI_SUCCESS;
}
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:19 UTC
Permalink
The entry point of the driver, InitializePciHostBridge(), leaks resources
(and installed protocols) in the following cases:

- The first root bridge protocol installation fails. In this case, the
host bridge protocol is left installed, but the driver exits with an
error.

- The second or a later root bridge protocol installation fails. In this
case, the host bridge protocol, and all prior root bridge protocols, are
left installed, even though the driver exits with an error.

Handle errors correctly: roll back / release / uninstall resources when
aborting the driver.

Cc: Jordan Justen <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
---
OvmfPkg/PciHostBridgeDxe/PciHostBridge.c | 54 ++++++++++++++++++--
1 file changed, 51 insertions(+), 3 deletions(-)

diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
index 7ca0b6e..a5dbe57 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
@@ -154,6 +154,32 @@ FreePrivateData:


/**
+ Uninitialize and free a root bridge set up with InitRootBridge().
+
+ On return, the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance and the device path
+ will have been released, freeing RootBus->Handle as well.
+
+ param[in] RootBus The private PCI_ROOT_BRIDGE_INSTANCE that has been created
+ with InitRootBridge(), and should be released.
+**/
+STATIC
+VOID
+UninitRootBridge (
+ IN PCI_ROOT_BRIDGE_INSTANCE *RootBus
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (RootBus->Handle,
+ &gEfiDevicePathProtocolGuid, &RootBus->DevicePath,
+ &gEfiPciRootBridgeIoProtocolGuid, &RootBus->Io,
+ NULL);
+ ASSERT_EFI_ERROR (Status);
+ FreePool (RootBus);
+}
+
+
+/**
Entry point of this driver

@param ImageHandle Handle of driver image
@@ -174,6 +200,7 @@ InitializePciHostBridge (
UINTN RootBridgeNumber;
PCI_HOST_BRIDGE_INSTANCE *HostBridge;
PCI_ROOT_BRIDGE_INSTANCE *RootBus;
+ EFI_STATUS UninstallStatus;

mDriverImageHandle = ImageHandle;

@@ -196,8 +223,7 @@ InitializePciHostBridge (
NULL
);
if (EFI_ERROR (Status)) {
- FreePool (HostBridge);
- return EFI_DEVICE_ERROR;
+ goto FreeHostBridge;
}

for (RootBridgeNumber = 0;
@@ -209,12 +235,34 @@ InitializePciHostBridge (
&RootBus
);
if (EFI_ERROR (Status)) {
- return Status;
+ goto RollbackProtocols;
}
InsertTailList (&HostBridge->Head, &RootBus->Link);
}

return EFI_SUCCESS;
+
+RollbackProtocols:
+ while (!IsListEmpty (&HostBridge->Head)) {
+ LIST_ENTRY *Entry;
+
+ Entry = GetFirstNode (&HostBridge->Head);
+ RemoveEntryList (Entry);
+ RootBus = DRIVER_INSTANCE_FROM_LIST_ENTRY (Entry);
+ UninitRootBridge (RootBus);
+ }
+ UninstallStatus = gBS->UninstallMultipleProtocolInterfaces (
+ HostBridge->HostBridgeHandle,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid,
+ &HostBridge->ResAlloc,
+ NULL
+ );
+ ASSERT_EFI_ERROR (UninstallStatus);
+
+FreeHostBridge:
+ FreePool (HostBridge);
+
+ return Status;
}
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:18 UTC
Permalink
This new function incorporates the current loop body found in the entry
point function, InitializePciHostBridge(). It will be called once for each
root bus discovered.

Cc: Jordan Justen <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
---
OvmfPkg/PciHostBridgeDxe/PciHostBridge.c | 126 ++++++++++++++------
1 file changed, 89 insertions(+), 37 deletions(-)

diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
index c2277bf..7ca0b6e 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
@@ -77,6 +77,83 @@ PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
//

/**
+ Allocate and initialize a root bridge.
+
+ param[in] RootBusNumber The bus number of the root bus (root bridge) to
+ create.
+ RootBusNumber is expected to fall into the valid
+ offset range of mResAperture.
+
+ param[in] HostBridgeHandle The EFI_HANDLE corresponding to the host bridge
+ that is the parent of the root bridge to create.
+ HostBridgeHandle is expected to have
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ installed on it.
+
+ param[out] RootBus The private PCI_ROOT_BRIDGE_INSTANCE that has
+ been created as the result of the function call.
+
+ @retval EFI_SUCCESS Initialization successful. A new
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL has been
+ created as the child of HostBridgeHandle. A
+ device path consisting of an ACPI device path
+ node, with UID = RootBusNumber, has been
+ installed on the same new handle.
+
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
+
+ @return Error codes from
+ gBS->InstallMultipleProtocolInterfaces().
+**/
+STATIC
+EFI_STATUS
+InitRootBridge (
+ IN UINT8 RootBusNumber,
+ IN EFI_HANDLE HostBridgeHandle,
+ OUT PCI_ROOT_BRIDGE_INSTANCE **RootBus
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ EFI_STATUS Status;
+
+ PrivateData = AllocateZeroPool (sizeof *PrivateData);
+ if (PrivateData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
+
+ CopyMem (&PrivateData->DevicePath, &mRootBridgeDevicePathTemplate,
+ sizeof mRootBridgeDevicePathTemplate);
+ PrivateData->DevicePath.AcpiDevicePath.UID = RootBusNumber;
+
+ //
+ // The function call below allocates no resources and performs no actions
+ // that have to be rolled back on later failure. It always succeeds.
+ //
+ Status = RootBridgeConstructor (&PrivateData->Io, HostBridgeHandle,
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM,
+ &mResAperture[RootBusNumber]);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->InstallMultipleProtocolInterfaces (&PrivateData->Handle,
+ &gEfiDevicePathProtocolGuid, &PrivateData->DevicePath,
+ &gEfiPciRootBridgeIoProtocolGuid, &PrivateData->Io,
+ NULL);
+ if (EFI_ERROR (Status)) {
+ goto FreePrivateData;
+ }
+
+ *RootBus = PrivateData;
+ return EFI_SUCCESS;
+
+FreePrivateData:
+ FreePool (PrivateData);
+ return Status;
+}
+
+
+/**
Entry point of this driver

@param ImageHandle Handle of driver image
@@ -94,9 +171,9 @@ InitializePciHostBridge (
)
{
EFI_STATUS Status;
- UINTN Loop2;
+ UINTN RootBridgeNumber;
PCI_HOST_BRIDGE_INSTANCE *HostBridge;
- PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBus;

mDriverImageHandle = ImageHandle;

@@ -123,43 +200,18 @@ InitializePciHostBridge (
return EFI_DEVICE_ERROR;
}

- //
- // Create Root Bridge Device Handle in this Host Bridge
- //
-
- for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) {
- PrivateData = AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE));
- if (PrivateData == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
-
- CopyMem (&PrivateData->DevicePath, &mRootBridgeDevicePathTemplate,
- sizeof mRootBridgeDevicePathTemplate);
- PrivateData->DevicePath.AcpiDevicePath.UID = Loop2;
-
- RootBridgeConstructor (
- &PrivateData->Io,
- HostBridge->HostBridgeHandle,
- EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM,
- &mResAperture[Loop2]
- );
-
- Status = gBS->InstallMultipleProtocolInterfaces(
- &PrivateData->Handle,
- &gEfiDevicePathProtocolGuid,
- &PrivateData->DevicePath,
- &gEfiPciRootBridgeIoProtocolGuid,
- &PrivateData->Io,
- NULL
- );
+ for (RootBridgeNumber = 0;
+ RootBridgeNumber < HostBridge->RootBridgeNumber;
+ ++RootBridgeNumber) {
+ Status = InitRootBridge (
+ (UINT8)RootBridgeNumber,
+ HostBridge->HostBridgeHandle,
+ &RootBus
+ );
if (EFI_ERROR (Status)) {
- FreePool(PrivateData);
- return EFI_DEVICE_ERROR;
+ return Status;
}
-
- InsertTailList (&HostBridge->Head, &PrivateData->Link);
+ InsertTailList (&HostBridge->Head, &RootBus->Link);
}

return EFI_SUCCESS;
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:22 UTC
Permalink
In this patch we assume that root bus number 0 is always there (same as
before), and scan the rest of the extra root buses, up to and including
255. When an extra root bus is found, we install the PCI root bridge IO
protocol for the previous root bus (which might be bus 0 or just the
previous extra root bus).

The root bridge protocol created thus will report the available bus number
range

[own bus number, next extra root bus number - 1]

The LHS of this interval will be used for the root bus's own number, and
the rest of the interval (which might encompass 0 additional elements too)
can be used by the PCI bus driver to assign subordinate bus numbers from.

(Subordinate buses are provided by PCI bridges that hang off the root bus
in question.)

For MMIO and IO space allocation, all the root buses share the original
[0x8000_0000, 0xFFFF_FFFF] and [0x0, 0xFFFF] ranges, respectively.

Cc: Jordan Justen <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
---
OvmfPkg/PciHostBridgeDxe/PciHostBridge.c | 95 +++++++++++++++-----
1 file changed, 71 insertions(+), 24 deletions(-)

diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
index 7dda75f..3486644 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
@@ -43,14 +43,6 @@ EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
}
};

-//
-// Hard code: Root Bridge's resource aperture
-//
-
-PCI_ROOT_BRIDGE_RESOURCE_APERTURE mResAperture[1] = {
- {0, 0xff, 0x80000000, 0xffffffff, 0, 0xffff}
-};
-
EFI_HANDLE mDriverImageHandle;

PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
@@ -80,8 +72,15 @@ PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {

param[in] RootBusNumber The bus number of the root bus (root bridge) to
create.
- RootBusNumber is expected to fall into the valid
- offset range of mResAperture.
+
+ param[in] MaxSubBusNumber The inclusive maximum bus number that can be
+ assigned to any subordinate bus found behind any
+ PCI bridge hanging off this root bus.
+
+ The caller is repsonsible for ensuring that
+ RootBusNumber <= MaxSubBusNumber. If
+ RootBusNumber equals MaxSubBusNumber, then the
+ root bus has no room for subordinate buses.

param[in] HostBridgeHandle The EFI_HANDLE corresponding to the host bridge
that is the parent of the root bridge to create.
@@ -108,12 +107,16 @@ STATIC
EFI_STATUS
InitRootBridge (
IN UINT8 RootBusNumber,
+ IN UINT8 MaxSubBusNumber,
IN EFI_HANDLE HostBridgeHandle,
OUT PCI_ROOT_BRIDGE_INSTANCE **RootBus
)
{
- PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
- EFI_STATUS Status;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ PCI_ROOT_BRIDGE_RESOURCE_APERTURE ResAperture;
+ EFI_STATUS Status;
+
+ ASSERT (RootBusNumber <= MaxSubBusNumber);

PrivateData = AllocateZeroPool (sizeof *PrivateData);
if (PrivateData == NULL) {
@@ -126,13 +129,18 @@ InitRootBridge (
sizeof mRootBridgeDevicePathTemplate);
PrivateData->DevicePath.AcpiDevicePath.UID = RootBusNumber;

+ ResAperture.BusBase = RootBusNumber;
+ ResAperture.BusLimit = MaxSubBusNumber;
+ ResAperture.MemBase = BASE_2GB;
+ ResAperture.MemLimit = BASE_4GB - 1;
+ ResAperture.IoBase = 0;
+ ResAperture.IoLimit = MAX_UINT16;
//
// The function call below allocates no resources and performs no actions
// that have to be rolled back on later failure. It always succeeds.
//
Status = RootBridgeConstructor (&PrivateData->Io, HostBridgeHandle,
- EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM,
- &mResAperture[RootBusNumber]);
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM, &ResAperture);
ASSERT_EFI_ERROR (Status);

Status = gBS->InstallMultipleProtocolInterfaces (&PrivateData->Handle,
@@ -143,6 +151,9 @@ InitRootBridge (
goto FreePrivateData;
}

+ DEBUG ((EFI_D_INFO,
+ "%a: installed root bus %d, with room for %d subordinate bus(es)\n",
+ __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));
*RootBus = PrivateData;
return EFI_SUCCESS;

@@ -196,6 +207,7 @@ InitializePciHostBridge (
)
{
EFI_STATUS Status;
+ UINTN LastRootBridgeNumber;
UINTN RootBridgeNumber;
PCI_HOST_BRIDGE_INSTANCE *HostBridge;
PCI_ROOT_BRIDGE_INSTANCE *RootBus;
@@ -224,19 +236,54 @@ InitializePciHostBridge (
goto FreeHostBridge;
}

- for (RootBridgeNumber = 0;
- RootBridgeNumber < 1;
+ //
+ // The "main" root bus is always there.
+ //
+ LastRootBridgeNumber = 0;
+
+ //
+ // Scan all other root buses. If function 0 of any device on a bus returns a
+ // VendorId register value different from all-bits-one, then that bus is
+ // alive.
+ //
+ for (RootBridgeNumber = 1;
+ RootBridgeNumber < 256;
++RootBridgeNumber) {
- Status = InitRootBridge (
- (UINT8)RootBridgeNumber,
- HostBridge->HostBridgeHandle,
- &RootBus
- );
- if (EFI_ERROR (Status)) {
- goto RollbackProtocols;
+ UINTN Device;
+
+ for (Device = 0; Device <= MAX_PCI_DEVICE_NUMBER; ++Device) {
+ if (PciRead16 (PCI_LIB_ADDRESS (RootBridgeNumber, Device, 0,
+ PCI_VENDOR_ID_OFFSET)) != MAX_UINT16) {
+ break;
+ }
}
- InsertTailList (&HostBridge->Head, &RootBus->Link);
+ if (Device <= MAX_PCI_DEVICE_NUMBER) {
+ //
+ // Found the next root bus. We can now install the *previous* one,
+ // because now we know how big a bus number range *that* one has, for any
+ // subordinate buses that might exist behind PCI bridges hanging off it.
+ //
+ Status = InitRootBridge ((UINT8)LastRootBridgeNumber,
+ (UINT8)(RootBridgeNumber - 1), HostBridge->HostBridgeHandle,
+ &RootBus);
+ if (EFI_ERROR (Status)) {
+ goto RollbackProtocols;
+ }
+ InsertTailList (&HostBridge->Head, &RootBus->Link);
+ LastRootBridgeNumber = RootBridgeNumber;
+ }
+ }
+
+ //
+ // Install the last root bus (which might be the only, ie. main, root bus, if
+ // we've found no extra root buses).
+ //
+ Status = InitRootBridge ((UINT8)LastRootBridgeNumber, 255,
+ HostBridge->HostBridgeHandle, &RootBus);
+ if (EFI_ERROR (Status)) {
+ goto RollbackProtocols;
}
+ InsertTailList (&HostBridge->Head, &RootBus->Link);

return EFI_SUCCESS;
--
1.8.3.1
Jordan Justen
2015-07-08 00:32:26 UTC
Permalink
Post by Laszlo Ersek
In this patch we assume that root bus number 0 is always there (same as
before), and scan the rest of the extra root buses, up to and including
255. When an extra root bus is found, we install the PCI root bridge IO
protocol for the previous root bus (which might be bus 0 or just the
previous extra root bus).
The root bridge protocol created thus will report the available bus number
range
[own bus number, next extra root bus number - 1]
The LHS of this interval will be used for the root bus's own number, and
the rest of the interval (which might encompass 0 additional elements too)
can be used by the PCI bus driver to assign subordinate bus numbers from.
(Subordinate buses are provided by PCI bridges that hang off the root bus
in question.)
For MMIO and IO space allocation, all the root buses share the original
[0x8000_0000, 0xFFFF_FFFF] and [0x0, 0xFFFF] ranges, respectively.
Contributed-under: TianoCore Contribution Agreement 1.0
---
OvmfPkg/PciHostBridgeDxe/PciHostBridge.c | 95 +++++++++++++++-----
1 file changed, 71 insertions(+), 24 deletions(-)
diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
index 7dda75f..3486644 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
@@ -43,14 +43,6 @@ EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
}
};
-//
-// Hard code: Root Bridge's resource aperture
-//
-
-PCI_ROOT_BRIDGE_RESOURCE_APERTURE mResAperture[1] = {
- {0, 0xff, 0x80000000, 0xffffffff, 0, 0xffff}
-};
-
EFI_HANDLE mDriverImageHandle;
PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
@@ -80,8 +72,15 @@ PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
param[in] RootBusNumber The bus number of the root bus (root bridge) to
create.
- RootBusNumber is expected to fall into the valid
- offset range of mResAperture.
+
+ param[in] MaxSubBusNumber The inclusive maximum bus number that can be
+ assigned to any subordinate bus found behind any
+ PCI bridge hanging off this root bus.
+
+ The caller is repsonsible for ensuring that
+ RootBusNumber <= MaxSubBusNumber. If
+ RootBusNumber equals MaxSubBusNumber, then the
+ root bus has no room for subordinate buses.
param[in] HostBridgeHandle The EFI_HANDLE corresponding to the host bridge
that is the parent of the root bridge to create.
@@ -108,12 +107,16 @@ STATIC
EFI_STATUS
InitRootBridge (
IN UINT8 RootBusNumber,
+ IN UINT8 MaxSubBusNumber,
IN EFI_HANDLE HostBridgeHandle,
OUT PCI_ROOT_BRIDGE_INSTANCE **RootBus
)
{
- PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
- EFI_STATUS Status;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ PCI_ROOT_BRIDGE_RESOURCE_APERTURE ResAperture;
+ EFI_STATUS Status;
+
+ ASSERT (RootBusNumber <= MaxSubBusNumber);
PrivateData = AllocateZeroPool (sizeof *PrivateData);
if (PrivateData == NULL) {
@@ -126,13 +129,18 @@ InitRootBridge (
sizeof mRootBridgeDevicePathTemplate);
PrivateData->DevicePath.AcpiDevicePath.UID = RootBusNumber;
+ ResAperture.BusBase = RootBusNumber;
+ ResAperture.BusLimit = MaxSubBusNumber;
+ ResAperture.MemBase = BASE_2GB;
+ ResAperture.MemLimit = BASE_4GB - 1;
+ ResAperture.IoBase = 0;
+ ResAperture.IoLimit = MAX_UINT16;
//
// The function call below allocates no resources and performs no actions
// that have to be rolled back on later failure. It always succeeds.
//
Status = RootBridgeConstructor (&PrivateData->Io, HostBridgeHandle,
- EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM,
- &mResAperture[RootBusNumber]);
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM, &ResAperture);
ASSERT_EFI_ERROR (Status);
Status = gBS->InstallMultipleProtocolInterfaces (&PrivateData->Handle,
@@ -143,6 +151,9 @@ InitRootBridge (
goto FreePrivateData;
}
+ DEBUG ((EFI_D_INFO,
+ "%a: installed root bus %d, with room for %d subordinate bus(es)\n",
+ __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));
*RootBus = PrivateData;
return EFI_SUCCESS;
@@ -196,6 +207,7 @@ InitializePciHostBridge (
)
{
EFI_STATUS Status;
+ UINTN LastRootBridgeNumber;
UINTN RootBridgeNumber;
PCI_HOST_BRIDGE_INSTANCE *HostBridge;
PCI_ROOT_BRIDGE_INSTANCE *RootBus;
@@ -224,19 +236,54 @@ InitializePciHostBridge (
goto FreeHostBridge;
}
- for (RootBridgeNumber = 0;
- RootBridgeNumber < 1;
+ //
+ // The "main" root bus is always there.
+ //
+ LastRootBridgeNumber = 0;
+
+ //
+ // Scan all other root buses. If function 0 of any device on a bus returns a
+ // VendorId register value different from all-bits-one, then that bus is
+ // alive.
+ //
+ for (RootBridgeNumber = 1;
+ RootBridgeNumber < 256;
Do we want to scan all these buses on Xen?
Post by Laszlo Ersek
++RootBridgeNumber) {
- Status = InitRootBridge (
- (UINT8)RootBridgeNumber,
- HostBridge->HostBridgeHandle,
- &RootBus
- );
- if (EFI_ERROR (Status)) {
- goto RollbackProtocols;
+ UINTN Device;
+
+ for (Device = 0; Device <= MAX_PCI_DEVICE_NUMBER; ++Device) {
I guess there's no guarantee that device 0 will be present on these
buses?

-Jordan
Post by Laszlo Ersek
+ if (PciRead16 (PCI_LIB_ADDRESS (RootBridgeNumber, Device, 0,
+ PCI_VENDOR_ID_OFFSET)) != MAX_UINT16) {
+ break;
+ }
}
- InsertTailList (&HostBridge->Head, &RootBus->Link);
+ if (Device <= MAX_PCI_DEVICE_NUMBER) {
+ //
+ // Found the next root bus. We can now install the *previous* one,
+ // because now we know how big a bus number range *that* one has, for any
+ // subordinate buses that might exist behind PCI bridges hanging off it.
+ //
+ Status = InitRootBridge ((UINT8)LastRootBridgeNumber,
+ (UINT8)(RootBridgeNumber - 1), HostBridge->HostBridgeHandle,
+ &RootBus);
+ if (EFI_ERROR (Status)) {
+ goto RollbackProtocols;
+ }
+ InsertTailList (&HostBridge->Head, &RootBus->Link);
+ LastRootBridgeNumber = RootBridgeNumber;
+ }
+ }
+
+ //
+ // Install the last root bus (which might be the only, ie. main, root bus, if
+ // we've found no extra root buses).
+ //
+ Status = InitRootBridge ((UINT8)LastRootBridgeNumber, 255,
+ HostBridge->HostBridgeHandle, &RootBus);
+ if (EFI_ERROR (Status)) {
+ goto RollbackProtocols;
}
+ InsertTailList (&HostBridge->Head, &RootBus->Link);
return EFI_SUCCESS;
--
1.8.3.1
Laszlo Ersek
2015-07-08 09:03:20 UTC
Permalink
Post by Jordan Justen
Post by Laszlo Ersek
In this patch we assume that root bus number 0 is always there (same as
before), and scan the rest of the extra root buses, up to and including
255. When an extra root bus is found, we install the PCI root bridge IO
protocol for the previous root bus (which might be bus 0 or just the
previous extra root bus).
The root bridge protocol created thus will report the available bus number
range
[own bus number, next extra root bus number - 1]
The LHS of this interval will be used for the root bus's own number, and
the rest of the interval (which might encompass 0 additional elements too)
can be used by the PCI bus driver to assign subordinate bus numbers from.
(Subordinate buses are provided by PCI bridges that hang off the root bus
in question.)
For MMIO and IO space allocation, all the root buses share the original
[0x8000_0000, 0xFFFF_FFFF] and [0x0, 0xFFFF] ranges, respectively.
Contributed-under: TianoCore Contribution Agreement 1.0
---
OvmfPkg/PciHostBridgeDxe/PciHostBridge.c | 95 +++++++++++++++-----
1 file changed, 71 insertions(+), 24 deletions(-)
diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
index 7dda75f..3486644 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
@@ -43,14 +43,6 @@ EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
}
};
-//
-// Hard code: Root Bridge's resource aperture
-//
-
-PCI_ROOT_BRIDGE_RESOURCE_APERTURE mResAperture[1] = {
- {0, 0xff, 0x80000000, 0xffffffff, 0, 0xffff}
-};
-
EFI_HANDLE mDriverImageHandle;
PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
@@ -80,8 +72,15 @@ PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
param[in] RootBusNumber The bus number of the root bus (root bridge) to
create.
- RootBusNumber is expected to fall into the valid
- offset range of mResAperture.
+
+ param[in] MaxSubBusNumber The inclusive maximum bus number that can be
+ assigned to any subordinate bus found behind any
+ PCI bridge hanging off this root bus.
+
+ The caller is repsonsible for ensuring that
+ RootBusNumber <= MaxSubBusNumber. If
+ RootBusNumber equals MaxSubBusNumber, then the
+ root bus has no room for subordinate buses.
param[in] HostBridgeHandle The EFI_HANDLE corresponding to the host bridge
that is the parent of the root bridge to create.
@@ -108,12 +107,16 @@ STATIC
EFI_STATUS
InitRootBridge (
IN UINT8 RootBusNumber,
+ IN UINT8 MaxSubBusNumber,
IN EFI_HANDLE HostBridgeHandle,
OUT PCI_ROOT_BRIDGE_INSTANCE **RootBus
)
{
- PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
- EFI_STATUS Status;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ PCI_ROOT_BRIDGE_RESOURCE_APERTURE ResAperture;
+ EFI_STATUS Status;
+
+ ASSERT (RootBusNumber <= MaxSubBusNumber);
PrivateData = AllocateZeroPool (sizeof *PrivateData);
if (PrivateData == NULL) {
@@ -126,13 +129,18 @@ InitRootBridge (
sizeof mRootBridgeDevicePathTemplate);
PrivateData->DevicePath.AcpiDevicePath.UID = RootBusNumber;
+ ResAperture.BusBase = RootBusNumber;
+ ResAperture.BusLimit = MaxSubBusNumber;
+ ResAperture.MemBase = BASE_2GB;
+ ResAperture.MemLimit = BASE_4GB - 1;
+ ResAperture.IoBase = 0;
+ ResAperture.IoLimit = MAX_UINT16;
//
// The function call below allocates no resources and performs no actions
// that have to be rolled back on later failure. It always succeeds.
//
Status = RootBridgeConstructor (&PrivateData->Io, HostBridgeHandle,
- EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM,
- &mResAperture[RootBusNumber]);
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM, &ResAperture);
ASSERT_EFI_ERROR (Status);
Status = gBS->InstallMultipleProtocolInterfaces (&PrivateData->Handle,
@@ -143,6 +151,9 @@ InitRootBridge (
goto FreePrivateData;
}
+ DEBUG ((EFI_D_INFO,
+ "%a: installed root bus %d, with room for %d subordinate bus(es)\n",
+ __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));
*RootBus = PrivateData;
return EFI_SUCCESS;
@@ -196,6 +207,7 @@ InitializePciHostBridge (
)
{
EFI_STATUS Status;
+ UINTN LastRootBridgeNumber;
UINTN RootBridgeNumber;
PCI_HOST_BRIDGE_INSTANCE *HostBridge;
PCI_ROOT_BRIDGE_INSTANCE *RootBus;
@@ -224,19 +236,54 @@ InitializePciHostBridge (
goto FreeHostBridge;
}
- for (RootBridgeNumber = 0;
- RootBridgeNumber < 1;
+ //
+ // The "main" root bus is always there.
+ //
+ LastRootBridgeNumber = 0;
+
+ //
+ // Scan all other root buses. If function 0 of any device on a bus returns a
+ // VendorId register value different from all-bits-one, then that bus is
+ // alive.
+ //
+ for (RootBridgeNumber = 1;
+ RootBridgeNumber < 256;
Do we want to scan all these buses on Xen?
Yes, but only if the tree is built at exactly this stage. This patch
introduces the generic scanning "algorithm", which should be correct on
Xen too. The only problem it has is its sub-optimal performance. So from
a correctness POV, this should work on Xen too.

In the next patch, we're going to short-circuit the scan if the
"etc/extra-pci-roots" fw_cfg file is absent (which should cover Xen).
Post by Jordan Justen
Post by Laszlo Ersek
++RootBridgeNumber) {
- Status = InitRootBridge (
- (UINT8)RootBridgeNumber,
- HostBridge->HostBridgeHandle,
- &RootBus
- );
- if (EFI_ERROR (Status)) {
- goto RollbackProtocols;
+ UINTN Device;
+
+ for (Device = 0; Device <= MAX_PCI_DEVICE_NUMBER; ++Device) {
I guess there's no guarantee that device 0 will be present on these
buses?
(I assume your question concerns a possibility to simplify the code,
eliminating this inner loop.)

No, that is not guaranteed. For example, in the following QEMU command
line fragment,

-device pxb,bus=pci.0,id=bridge2,bus_nr=7 \
-netdev user,id=netdev1 \
-device virtio-net-pci,netdev=netdev1,bus=bridge2,addr=3

the virtio-net NIC will be the only device on the extra root bus in
question, and its Device value (practically: PCI slot on the extra root
bus) will be 3 (from addr=3). Device=0 will not respond.

Thanks
Laszlo
Post by Jordan Justen
-Jordan
Post by Laszlo Ersek
+ if (PciRead16 (PCI_LIB_ADDRESS (RootBridgeNumber, Device, 0,
+ PCI_VENDOR_ID_OFFSET)) != MAX_UINT16) {
+ break;
+ }
}
- InsertTailList (&HostBridge->Head, &RootBus->Link);
+ if (Device <= MAX_PCI_DEVICE_NUMBER) {
+ //
+ // Found the next root bus. We can now install the *previous* one,
+ // because now we know how big a bus number range *that* one has, for any
+ // subordinate buses that might exist behind PCI bridges hanging off it.
+ //
+ Status = InitRootBridge ((UINT8)LastRootBridgeNumber,
+ (UINT8)(RootBridgeNumber - 1), HostBridge->HostBridgeHandle,
+ &RootBus);
+ if (EFI_ERROR (Status)) {
+ goto RollbackProtocols;
+ }
+ InsertTailList (&HostBridge->Head, &RootBus->Link);
+ LastRootBridgeNumber = RootBridgeNumber;
+ }
+ }
+
+ //
+ // Install the last root bus (which might be the only, ie. main, root bus, if
+ // we've found no extra root buses).
+ //
+ Status = InitRootBridge ((UINT8)LastRootBridgeNumber, 255,
+ HostBridge->HostBridgeHandle, &RootBus);
+ if (EFI_ERROR (Status)) {
+ goto RollbackProtocols;
}
+ InsertTailList (&HostBridge->Head, &RootBus->Link);
return EFI_SUCCESS;
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:21 UTC
Permalink
This field was supposed to store the number of root buses created; however
we don't need to keep that count persistently. After the entry point returns,
nothing reads this field.

Cc: Jordan Justen <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
---
OvmfPkg/PciHostBridgeDxe/PciHostBridge.h | 1 -
OvmfPkg/PciHostBridgeDxe/PciHostBridge.c | 4 +---
2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
index d2c28bc..617c68e 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
@@ -52,7 +52,6 @@ typedef enum {
typedef struct {
UINTN Signature;
EFI_HANDLE HostBridgeHandle;
- UINTN RootBridgeNumber;
LIST_ENTRY Head;
BOOLEAN ResourceSubmited;
BOOLEAN CanRestarted;
diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
index a5dbe57..7dda75f 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
@@ -56,7 +56,6 @@ EFI_HANDLE mDriverImageHandle;
PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
PCI_HOST_BRIDGE_SIGNATURE, // Signature
NULL, // HostBridgeHandle
- 0, // RootBridgeNumber
{NULL, NULL}, // Head
FALSE, // ResourceSubiteed
TRUE, // CanRestarted
@@ -213,7 +212,6 @@ InitializePciHostBridge (
return EFI_OUT_OF_RESOURCES;
}

- HostBridge->RootBridgeNumber = 1;
InitializeListHead (&HostBridge->Head);

Status = gBS->InstallMultipleProtocolInterfaces (
@@ -227,7 +225,7 @@ InitializePciHostBridge (
}

for (RootBridgeNumber = 0;
- RootBridgeNumber < HostBridge->RootBridgeNumber;
+ RootBridgeNumber < 1;
++RootBridgeNumber) {
Status = InitRootBridge (
(UINT8)RootBridgeNumber,
--
1.8.3.1
Jordan Justen
2015-07-08 00:27:03 UTC
Permalink
Post by Laszlo Ersek
This field was supposed to store the number of root buses created; however
we don't need to keep that count persistently. After the entry point returns,
nothing reads this field.
Contributed-under: TianoCore Contribution Agreement 1.0
---
OvmfPkg/PciHostBridgeDxe/PciHostBridge.h | 1 -
OvmfPkg/PciHostBridgeDxe/PciHostBridge.c | 4 +---
2 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
index d2c28bc..617c68e 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.h
@@ -52,7 +52,6 @@ typedef enum {
typedef struct {
UINTN Signature;
EFI_HANDLE HostBridgeHandle;
- UINTN RootBridgeNumber;
LIST_ENTRY Head;
BOOLEAN ResourceSubmited;
BOOLEAN CanRestarted;
diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
index a5dbe57..7dda75f 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
@@ -56,7 +56,6 @@ EFI_HANDLE mDriverImageHandle;
PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
PCI_HOST_BRIDGE_SIGNATURE, // Signature
NULL, // HostBridgeHandle
- 0, // RootBridgeNumber
{NULL, NULL}, // Head
FALSE, // ResourceSubiteed
TRUE, // CanRestarted
@@ -213,7 +212,6 @@ InitializePciHostBridge (
return EFI_OUT_OF_RESOURCES;
}
- HostBridge->RootBridgeNumber = 1;
InitializeListHead (&HostBridge->Head);
Status = gBS->InstallMultipleProtocolInterfaces (
@@ -227,7 +225,7 @@ InitializePciHostBridge (
}
for (RootBridgeNumber = 0;
- RootBridgeNumber < HostBridge->RootBridgeNumber;
+ RootBridgeNumber < 1;
++RootBridgeNumber) {
Status = InitRootBridge (
(UINT8)RootBridgeNumber,
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:24 UTC
Permalink
SeaBIOS requires the OpenFirmware device paths exported in the "bootorder"
fw-cfg file to refer to extra (PXB) root buses by their relative positions
(in increasing bus number order) rather than by actual bus numbers.

However, OVMF's PCI host bridge / root bridge driver creates PciRoot(UID)
device path nodes for extra PCI root buses with UID=bus_nr, not position.
(These ACPI devpath UID values must, and do, match the UID values exposed
in QEMU's ACPI payload, generated for PXB root buses.)

Therefore the boot order matching logic will have to map extra root bus
positions to bus numbers. Add a small group of utility functions to help
with that.

Cc: Jordan Justen <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
---

Notes:
v2:
- new in v2

OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf | 6 +
OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.h | 40 +++
OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.c | 313 ++++++++++++++++++++
3 files changed, 359 insertions(+)

diff --git a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
index e972ae9..1024328 100644
--- a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
+++ b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
@@ -32,6 +32,7 @@ [Defines]

[Sources]
QemuBootOrderLib.c
+ ExtraRootBusMap.c

[Packages]
MdePkg/MdePkg.dec
@@ -49,6 +50,7 @@ [LibraryClasses]
PrintLib
DevicePathLib
BaseMemoryLib
+ OrderedCollectionLib

[Guids]
gEfiGlobalVariableGuid
@@ -60,3 +62,7 @@ [FeaturePcd]

[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
+
+[Protocols]
+ gEfiDevicePathProtocolGuid ## CONSUMES
+ gEfiPciRootBridgeIoProtocolGuid ## CONSUMES
diff --git a/OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.h b/OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.h
new file mode 100644
index 0000000..e2dbc38
--- /dev/null
+++ b/OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.h
@@ -0,0 +1,40 @@
+/** @file
+ Map positions of extra PCI root buses to bus numbers.
+
+ Copyright (C) 2015, Red Hat, Inc.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#ifndef __EXTRA_ROOT_BUS_MAP_H__
+#define __EXTRA_ROOT_BUS_MAP_H__
+
+/**
+ Incomplete ("opaque") data type implementing the map.
+**/
+typedef struct EXTRA_ROOT_BUS_MAP_STRUCT EXTRA_ROOT_BUS_MAP;
+
+EFI_STATUS
+CreateExtraRootBusMap (
+ OUT EXTRA_ROOT_BUS_MAP **ExtraRootBusMap
+ );
+
+VOID
+DestroyExtraRootBusMap (
+ IN EXTRA_ROOT_BUS_MAP *ExtraRootBusMap
+ );
+
+EFI_STATUS
+MapRootBusPosToBusNr (
+ IN CONST EXTRA_ROOT_BUS_MAP *ExtraRootBusMap,
+ IN UINT64 RootBusPos,
+ OUT UINT32 *RootBusNr
+ );
+
+#endif
diff --git a/OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.c b/OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.c
new file mode 100644
index 0000000..ec42214
--- /dev/null
+++ b/OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.c
@@ -0,0 +1,313 @@
+/** @file
+ Map positions of extra PCI root buses to bus numbers.
+
+ Copyright (C) 2015, Red Hat, Inc.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/OrderedCollectionLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/PciRootBridgeIo.h>
+
+#include "ExtraRootBusMap.h"
+
+//
+// The BusNumbers field is an array with Count elements. The elements increase
+// strictry monotonically. Zero is not an element (because the zero bus number
+// belongs to the "main" root bus, never to an extra root bus). Offset N in the
+// array maps the extra root bus with position (N+1) to its bus number (because
+// the root bus with position 0 is always the main root bus, therefore we don't
+// store it).
+//
+// If there are no extra root buses in the system, then Count is 0, and
+// BusNumbers is NULL.
+//
+struct EXTRA_ROOT_BUS_MAP_STRUCT {
+ UINT32 *BusNumbers;
+ UINTN Count;
+};
+
+
+/**
+ An ORDERED_COLLECTION_USER_COMPARE function that compares root bridge
+ protocol device paths based on UID.
+
+ @param[in] UserStruct1 Pointer to the first ACPI_HID_DEVICE_PATH.
+
+ @param[in] UserStruct2 Pointer to the second ACPI_HID_DEVICE_PATH.
+
+ @retval <0 If UserStruct1 compares less than UserStruct2.
+
+ @retval 0 If UserStruct1 compares equal to UserStruct2.
+
+ @retval >0 If UserStruct1 compares greater than UserStruct2.
+**/
+STATIC
+INTN
+EFIAPI
+RootBridgePathCompare (
+ IN CONST VOID *UserStruct1,
+ IN CONST VOID *UserStruct2
+ )
+{
+ CONST ACPI_HID_DEVICE_PATH *Acpi1;
+ CONST ACPI_HID_DEVICE_PATH *Acpi2;
+
+ Acpi1 = UserStruct1;
+ Acpi2 = UserStruct2;
+
+ return Acpi1->UID < Acpi2->UID ? -1 :
+ Acpi1->UID > Acpi2->UID ? 1 :
+ 0;
+}
+
+
+/**
+ An ORDERED_COLLECTION_KEY_COMPARE function that compares a root bridge
+ protocol device path against a UID.
+
+ @param[in] StandaloneKey Pointer to the bare UINT32 UID.
+
+ @param[in] UserStruct Pointer to the ACPI_HID_DEVICE_PATH with the
+ embedded UINT32 UID.
+
+ @retval <0 If StandaloneKey compares less than UserStruct's key.
+
+ @retval 0 If StandaloneKey compares equal to UserStruct's key.
+
+ @retval >0 If StandaloneKey compares greater than UserStruct's key.
+**/
+STATIC
+INTN
+EFIAPI
+RootBridgePathKeyCompare (
+ IN CONST VOID *StandaloneKey,
+ IN CONST VOID *UserStruct
+ )
+{
+ CONST UINT32 *Uid;
+ CONST ACPI_HID_DEVICE_PATH *Acpi;
+
+ Uid = StandaloneKey;
+ Acpi = UserStruct;
+
+ return *Uid < Acpi->UID ? -1 :
+ *Uid > Acpi->UID ? 1 :
+ 0;
+}
+
+
+/**
+ Create a structure that maps the relative positions of PCI root buses to bus
+ numbers.
+
+ In the "bootorder" fw_cfg file, QEMU refers to extra PCI root buses by their
+ positions, in relative root bus number order, not by their actual PCI bus
+ numbers. The ACPI HID device path nodes however that are associated with
+ PciRootBridgeIo protocol instances in the system have their UID fields set to
+ the bus numbers. Create a map that gives, for each extra PCI root bus's
+ position (ie. "serial number") its actual PCI bus number.
+
+ @param[out] ExtraRootBusMap The data structure implementing the map.
+
+ @retval EFI_SUCCESS ExtraRootBusMap has been populated.
+
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
+
+ @retval EFI_ALREADY_STARTED A duplicate root bus number has been found in
+ the system. (This should never happen.)
+
+ @return Error codes returned by
+ gBS->LocateHandleBuffer() and
+ gBS->HandleProtocol().
+
+**/
+EFI_STATUS
+CreateExtraRootBusMap (
+ OUT EXTRA_ROOT_BUS_MAP **ExtraRootBusMap
+ )
+{
+ EFI_STATUS Status;
+ UINTN NumHandles;
+ EFI_HANDLE *Handles;
+ ORDERED_COLLECTION *Collection;
+ EXTRA_ROOT_BUS_MAP *Map;
+ UINTN Idx;
+ ORDERED_COLLECTION_ENTRY *Entry, *Entry2;
+
+ //
+ // Handles and Collection are temporary / helper variables, while in Map we
+ // build the return value.
+ //
+
+ Status = gBS->LocateHandleBuffer (ByProtocol,
+ &gEfiPciRootBridgeIoProtocolGuid, NULL /* SearchKey */,
+ &NumHandles, &Handles);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Collection = OrderedCollectionInit (RootBridgePathCompare,
+ RootBridgePathKeyCompare);
+ if (Collection == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeHandles;
+ }
+
+ Map = AllocateZeroPool (sizeof *Map);
+ if (Map == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeCollection;
+ }
+
+ //
+ // Collect the ACPI device path protocols of the root bridges.
+ //
+ for (Idx = 0; Idx < NumHandles; ++Idx) {
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ Status = gBS->HandleProtocol (Handles[Idx], &gEfiDevicePathProtocolGuid,
+ (VOID**)&DevicePath);
+ if (EFI_ERROR (Status)) {
+ goto FreeMap;
+ }
+
+ //
+ // Examine if the device path is an ACPI HID one, and if so, if UID is
+ // nonzero (ie. the root bridge that the bus number belongs to is "extra",
+ // not the main one). In that case, link the device path into Collection.
+ //
+ if (DevicePathType (DevicePath) == ACPI_DEVICE_PATH &&
+ DevicePathSubType (DevicePath) == ACPI_DP &&
+ ((ACPI_HID_DEVICE_PATH *)DevicePath)->HID == EISA_PNP_ID(0x0A03) &&
+ ((ACPI_HID_DEVICE_PATH *)DevicePath)->UID > 0) {
+ Status = OrderedCollectionInsert (Collection, NULL, DevicePath);
+ if (EFI_ERROR (Status)) {
+ goto FreeMap;
+ }
+ ++Map->Count;
+ }
+ }
+
+ if (Map->Count > 0) {
+ //
+ // At least one extra PCI root bus exists.
+ //
+ Map->BusNumbers = AllocatePool (Map->Count * sizeof *Map->BusNumbers);
+ if (Map->BusNumbers == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeMap;
+ }
+ }
+
+ //
+ // Now collect the bus numbers of the extra PCI root buses into Map.
+ //
+ Idx = 0;
+ Entry = OrderedCollectionMin (Collection);
+ while (Idx < Map->Count) {
+ ACPI_HID_DEVICE_PATH *Acpi;
+
+ ASSERT (Entry != NULL);
+ Acpi = OrderedCollectionUserStruct (Entry);
+ Map->BusNumbers[Idx] = Acpi->UID;
+ DEBUG ((EFI_D_VERBOSE,
+ "%a: extra bus position 0x%Lx maps to bus number (UID) 0x%x\n",
+ __FUNCTION__, (UINT64)(Idx + 1), Acpi->UID));
+ ++Idx;
+ Entry = OrderedCollectionNext (Entry);
+ }
+ ASSERT (Entry == NULL);
+
+ *ExtraRootBusMap = Map;
+ Status = EFI_SUCCESS;
+
+ //
+ // Fall through in order to release temporaries.
+ //
+
+FreeMap:
+ if (EFI_ERROR (Status)) {
+ if (Map->BusNumbers != NULL) {
+ FreePool (Map->BusNumbers);
+ }
+ FreePool (Map);
+ }
+
+FreeCollection:
+ for (Entry = OrderedCollectionMin (Collection); Entry != NULL;
+ Entry = Entry2) {
+ Entry2 = OrderedCollectionNext (Entry);
+ OrderedCollectionDelete (Collection, Entry, NULL);
+ }
+ OrderedCollectionUninit (Collection);
+
+FreeHandles:
+ FreePool (Handles);
+
+ return Status;
+}
+
+
+/**
+ Release a map created with CreateExtraRootBusMap().
+
+ @param[in] ExtraRootBusMap The map to release.
+*/
+VOID
+DestroyExtraRootBusMap (
+ IN EXTRA_ROOT_BUS_MAP *ExtraRootBusMap
+ )
+{
+ if (ExtraRootBusMap->BusNumbers != NULL) {
+ FreePool (ExtraRootBusMap->BusNumbers);
+ }
+ FreePool (ExtraRootBusMap);
+}
+
+/**
+ Map the position (serial number) of an extra PCI root bus to its bus number.
+
+ @param[in] ExtraRootBusMap The map created with CreateExtraRootBusMap();
+
+ @param[in] RootBusPos The extra PCI root bus position to map.
+
+ @param[out] RootBusNr The bus number belonging to the extra PCI root
+ bus identified by RootBusPos.
+
+ @retval EFI_INVALID_PARAMETER RootBusPos is zero. The zero position
+ identifies the main root bus, whose bus number
+ is always zero, and is therefore never
+ maintained in ExtraRootBusMap.
+
+ @retval EFI_NOT_FOUND RootBusPos is not found in ExtraRootBusMap.
+
+ @retval EFI_SUCCESS Mapping successful.
+**/
+EFI_STATUS
+MapRootBusPosToBusNr (
+ IN CONST EXTRA_ROOT_BUS_MAP *ExtraRootBusMap,
+ IN UINT64 RootBusPos,
+ OUT UINT32 *RootBusNr
+ )
+{
+ if (RootBusPos == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (RootBusPos > ExtraRootBusMap->Count) {
+ return EFI_NOT_FOUND;
+ }
+ *RootBusNr = ExtraRootBusMap->BusNumbers[RootBusPos - 1];
+ return EFI_SUCCESS;
+}
--
1.8.3.1
Jordan Justen
2015-07-13 22:37:01 UTC
Permalink
Post by Laszlo Ersek
SeaBIOS requires the OpenFirmware device paths exported in the "bootorder"
fw-cfg file to refer to extra (PXB) root buses by their relative positions
(in increasing bus number order) rather than by actual bus numbers.
However, OVMF's PCI host bridge / root bridge driver creates PciRoot(UID)
device path nodes for extra PCI root buses with UID=bus_nr, not position.
(These ACPI devpath UID values must, and do, match the UID values exposed
in QEMU's ACPI payload, generated for PXB root buses.)
Therefore the boot order matching logic will have to map extra root bus
positions to bus numbers. Add a small group of utility functions to help
with that.
Contributed-under: TianoCore Contribution Agreement 1.0
---
- new in v2
OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf | 6 +
OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.h | 40 +++
OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.c | 313 ++++++++++++++++++++
3 files changed, 359 insertions(+)
diff --git a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
index e972ae9..1024328 100644
--- a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
+++ b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
@@ -32,6 +32,7 @@ [Defines]
[Sources]
QemuBootOrderLib.c
+ ExtraRootBusMap.c
[Packages]
MdePkg/MdePkg.dec
@@ -49,6 +50,7 @@ [LibraryClasses]
PrintLib
DevicePathLib
BaseMemoryLib
+ OrderedCollectionLib
[Guids]
gEfiGlobalVariableGuid
@@ -60,3 +62,7 @@ [FeaturePcd]
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
+
+[Protocols]
+ gEfiDevicePathProtocolGuid ## CONSUMES
+ gEfiPciRootBridgeIoProtocolGuid ## CONSUMES
diff --git a/OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.h b/OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.h
new file mode 100644
index 0000000..e2dbc38
--- /dev/null
+++ b/OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.h
@@ -0,0 +1,40 @@
+ Map positions of extra PCI root buses to bus numbers.
+
+ Copyright (C) 2015, Red Hat, Inc.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#ifndef __EXTRA_ROOT_BUS_MAP_H__
+#define __EXTRA_ROOT_BUS_MAP_H__
+
+/**
+ Incomplete ("opaque") data type implementing the map.
+**/
+typedef struct EXTRA_ROOT_BUS_MAP_STRUCT EXTRA_ROOT_BUS_MAP;
+
+EFI_STATUS
+CreateExtraRootBusMap (
+ OUT EXTRA_ROOT_BUS_MAP **ExtraRootBusMap
+ );
+
+VOID
+DestroyExtraRootBusMap (
+ IN EXTRA_ROOT_BUS_MAP *ExtraRootBusMap
+ );
+
+EFI_STATUS
+MapRootBusPosToBusNr (
+ IN CONST EXTRA_ROOT_BUS_MAP *ExtraRootBusMap,
+ IN UINT64 RootBusPos,
+ OUT UINT32 *RootBusNr
+ );
+
+#endif
diff --git a/OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.c b/OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.c
new file mode 100644
index 0000000..ec42214
--- /dev/null
+++ b/OvmfPkg/Library/QemuBootOrderLib/ExtraRootBusMap.c
@@ -0,0 +1,313 @@
+ Map positions of extra PCI root buses to bus numbers.
+
+ Copyright (C) 2015, Red Hat, Inc.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/OrderedCollectionLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/PciRootBridgeIo.h>
+
+#include "ExtraRootBusMap.h"
+
+//
+// The BusNumbers field is an array with Count elements. The elements increase
+// strictry monotonically. Zero is not an element (because the zero bus number
+// belongs to the "main" root bus, never to an extra root bus). Offset N in the
+// array maps the extra root bus with position (N+1) to its bus number (because
+// the root bus with position 0 is always the main root bus, therefore we don't
+// store it).
+//
+// If there are no extra root buses in the system, then Count is 0, and
+// BusNumbers is NULL.
+//
+struct EXTRA_ROOT_BUS_MAP_STRUCT {
+ UINT32 *BusNumbers;
+ UINTN Count;
+};
+
+
+/**
+ An ORDERED_COLLECTION_USER_COMPARE function that compares root bridge
+ protocol device paths based on UID.
+
+
+
+
+
+**/
+STATIC
+INTN
+EFIAPI
+RootBridgePathCompare (
+ IN CONST VOID *UserStruct1,
+ IN CONST VOID *UserStruct2
+ )
+{
+ CONST ACPI_HID_DEVICE_PATH *Acpi1;
+ CONST ACPI_HID_DEVICE_PATH *Acpi2;
+
+ Acpi1 = UserStruct1;
+ Acpi2 = UserStruct2;
+
+ 0;
+}
+
+
+/**
+ An ORDERED_COLLECTION_KEY_COMPARE function that compares a root bridge
+ protocol device path against a UID.
+
+
+ embedded UINT32 UID.
+
+
+
+**/
+STATIC
+INTN
+EFIAPI
+RootBridgePathKeyCompare (
+ IN CONST VOID *StandaloneKey,
+ IN CONST VOID *UserStruct
+ )
+{
+ CONST UINT32 *Uid;
+ CONST ACPI_HID_DEVICE_PATH *Acpi;
+
+ Uid = StandaloneKey;
+ Acpi = UserStruct;
+
+ 0;
+}
+
+
+/**
+ Create a structure that maps the relative positions of PCI root buses to bus
+ numbers.
+
+ In the "bootorder" fw_cfg file, QEMU refers to extra PCI root buses by their
+ positions, in relative root bus number order, not by their actual PCI bus
+ numbers. The ACPI HID device path nodes however that are associated with
+ PciRootBridgeIo protocol instances in the system have their UID fields set to
+ the bus numbers. Create a map that gives, for each extra PCI root bus's
+ position (ie. "serial number") its actual PCI bus number.
+
+
+
+
+ the system. (This should never happen.)
+
+ gBS->LocateHandleBuffer() and
+ gBS->HandleProtocol().
+
+**/
+EFI_STATUS
+CreateExtraRootBusMap (
+ OUT EXTRA_ROOT_BUS_MAP **ExtraRootBusMap
+ )
+{
+ EFI_STATUS Status;
+ UINTN NumHandles;
+ EFI_HANDLE *Handles;
+ ORDERED_COLLECTION *Collection;
+ EXTRA_ROOT_BUS_MAP *Map;
+ UINTN Idx;
+ ORDERED_COLLECTION_ENTRY *Entry, *Entry2;
+
+ //
+ // Handles and Collection are temporary / helper variables, while in Map we
+ // build the return value.
+ //
+
+ Status = gBS->LocateHandleBuffer (ByProtocol,
+ &gEfiPciRootBridgeIoProtocolGuid, NULL /* SearchKey */,
+ &NumHandles, &Handles);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Collection = OrderedCollectionInit (RootBridgePathCompare,
+ RootBridgePathKeyCompare);
+ if (Collection == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeHandles;
+ }
+
+ Map = AllocateZeroPool (sizeof *Map);
+ if (Map == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeCollection;
+ }
+
+ //
+ // Collect the ACPI device path protocols of the root bridges.
+ //
+ for (Idx = 0; Idx < NumHandles; ++Idx) {
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ Status = gBS->HandleProtocol (Handles[Idx], &gEfiDevicePathProtocolGuid,
+ (VOID**)&DevicePath);
+ if (EFI_ERROR (Status)) {
+ goto FreeMap;
+ }
+
+ //
+ // Examine if the device path is an ACPI HID one, and if so, if UID is
+ // nonzero (ie. the root bridge that the bus number belongs to is "extra",
+ // not the main one). In that case, link the device path into Collection.
+ //
+ if (DevicePathType (DevicePath) == ACPI_DEVICE_PATH &&
+ DevicePathSubType (DevicePath) == ACPI_DP &&
+ ((ACPI_HID_DEVICE_PATH *)DevicePath)->HID == EISA_PNP_ID(0x0A03) &&
+ ((ACPI_HID_DEVICE_PATH *)DevicePath)->UID > 0) {
+ Status = OrderedCollectionInsert (Collection, NULL, DevicePath);
+ if (EFI_ERROR (Status)) {
+ goto FreeMap;
+ }
+ ++Map->Count;
+ }
+ }
+
+ if (Map->Count > 0) {
+ //
+ // At least one extra PCI root bus exists.
+ //
+ Map->BusNumbers = AllocatePool (Map->Count * sizeof *Map->BusNumbers);
+ if (Map->BusNumbers == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeMap;
+ }
+ }
+
+ //
+ // Now collect the bus numbers of the extra PCI root buses into Map.
+ //
+ Idx = 0;
+ Entry = OrderedCollectionMin (Collection);
+ while (Idx < Map->Count) {
+ ACPI_HID_DEVICE_PATH *Acpi;
+
+ ASSERT (Entry != NULL);
+ Acpi = OrderedCollectionUserStruct (Entry);
+ Map->BusNumbers[Idx] = Acpi->UID;
+ DEBUG ((EFI_D_VERBOSE,
+ "%a: extra bus position 0x%Lx maps to bus number (UID) 0x%x\n",
+ __FUNCTION__, (UINT64)(Idx + 1), Acpi->UID));
+ ++Idx;
+ Entry = OrderedCollectionNext (Entry);
+ }
+ ASSERT (Entry == NULL);
+
+ *ExtraRootBusMap = Map;
+ Status = EFI_SUCCESS;
+
+ //
+ // Fall through in order to release temporaries.
+ //
+
+ if (EFI_ERROR (Status)) {
+ if (Map->BusNumbers != NULL) {
+ FreePool (Map->BusNumbers);
+ }
+ FreePool (Map);
+ }
+
+ for (Entry = OrderedCollectionMin (Collection); Entry != NULL;
+ Entry = Entry2) {
+ Entry2 = OrderedCollectionNext (Entry);
+ OrderedCollectionDelete (Collection, Entry, NULL);
+ }
+ OrderedCollectionUninit (Collection);
+
+ FreePool (Handles);
+
+ return Status;
+}
+
+
+/**
+ Release a map created with CreateExtraRootBusMap().
+
+*/
+VOID
+DestroyExtraRootBusMap (
+ IN EXTRA_ROOT_BUS_MAP *ExtraRootBusMap
+ )
+{
+ if (ExtraRootBusMap->BusNumbers != NULL) {
+ FreePool (ExtraRootBusMap->BusNumbers);
+ }
+ FreePool (ExtraRootBusMap);
+}
+
+/**
+ Map the position (serial number) of an extra PCI root bus to its bus number.
+
+
+
+ bus identified by RootBusPos.
+
+ identifies the main root bus, whose bus number
+ is always zero, and is therefore never
+ maintained in ExtraRootBusMap.
+
+
+**/
+EFI_STATUS
+MapRootBusPosToBusNr (
+ IN CONST EXTRA_ROOT_BUS_MAP *ExtraRootBusMap,
+ IN UINT64 RootBusPos,
+ OUT UINT32 *RootBusNr
+ )
+{
+ if (RootBusPos == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (RootBusPos > ExtraRootBusMap->Count) {
+ return EFI_NOT_FOUND;
+ }
+ *RootBusNr = ExtraRootBusMap->BusNumbers[RootBusPos - 1];
+ return EFI_SUCCESS;
+}
--
1.8.3.1
Laszlo Ersek
2015-07-07 15:09:23 UTC
Permalink
QEMU provides an fw_cfg file called "etc/extra-pci-roots", containing a
little-endian UINT64 value that exposes the number of extra root buses. We
can use this value to terminate the scan as soon as we find the last extra
root bus.

Cc: Jordan Justen <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Regression-tested-by: Gabriel Somlo <***@cmu.edu>
---

Notes:
v2:
- %Lu is available now in format strings, for printing UINT64 values in
decimal

OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf | 2 ++
OvmfPkg/PciHostBridgeDxe/PciHostBridge.c | 22 +++++++++++++++++++-
2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf b/OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
index 40f4c3c..ca760b5 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
@@ -26,6 +26,7 @@ [Defines]

[Packages]
MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec

[LibraryClasses]
UefiDriverEntryPoint
@@ -39,6 +40,7 @@ [LibraryClasses]
DevicePathLib
IoLib
PciLib
+ QemuFwCfgLib

[Sources]
PciHostBridge.c
diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
index 3486644..efef2ed 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
@@ -15,6 +15,8 @@

**/

+#include <Library/QemuFwCfgLib.h>
+
#include "PciHostBridge.h"

STATIC
@@ -207,6 +209,9 @@ InitializePciHostBridge (
)
{
EFI_STATUS Status;
+ FIRMWARE_CONFIG_ITEM FwCfgItem;
+ UINTN FwCfgSize;
+ UINT64 ExtraRootBridgesLeft;
UINTN LastRootBridgeNumber;
UINTN RootBridgeNumber;
PCI_HOST_BRIDGE_INSTANCE *HostBridge;
@@ -237,6 +242,20 @@ InitializePciHostBridge (
}

//
+ // QEMU provides the number of extra root buses, shortening the exhaustive
+ // search below. If there is no hint, the feature is missing.
+ //
+ Status = QemuFwCfgFindFile ("etc/extra-pci-roots", &FwCfgItem, &FwCfgSize);
+ if (EFI_ERROR (Status) || FwCfgSize != sizeof ExtraRootBridgesLeft) {
+ ExtraRootBridgesLeft = 0;
+ } else {
+ QemuFwCfgSelectItem (FwCfgItem);
+ QemuFwCfgReadBytes (FwCfgSize, &ExtraRootBridgesLeft);
+ DEBUG ((EFI_D_INFO, "%a: %Lu extra root buses reported by QEMU\n",
+ __FUNCTION__, ExtraRootBridgesLeft));
+ }
+
+ //
// The "main" root bus is always there.
//
LastRootBridgeNumber = 0;
@@ -247,7 +266,7 @@ InitializePciHostBridge (
// alive.
//
for (RootBridgeNumber = 1;
- RootBridgeNumber < 256;
+ RootBridgeNumber < 256 && ExtraRootBridgesLeft > 0;
++RootBridgeNumber) {
UINTN Device;

@@ -271,6 +290,7 @@ InitializePciHostBridge (
}
InsertTailList (&HostBridge->Head, &RootBus->Link);
LastRootBridgeNumber = RootBridgeNumber;
+ --ExtraRootBridgesLeft;
}
}
--
1.8.3.1
Jordan Justen
2015-07-08 00:38:26 UTC
Permalink
Post by Laszlo Ersek
QEMU provides an fw_cfg file called "etc/extra-pci-roots", containing a
How long were the extra roots in qemu without the fw_cfg entry?

That's a leading question for, what if we only were to only scan for
the roots if the fw_cfg entry is present?

Does seabios scan up to 255 if the fw_cfg entry is not found?

-Jordan
Post by Laszlo Ersek
little-endian UINT64 value that exposes the number of extra root buses. We
can use this value to terminate the scan as soon as we find the last extra
root bus.
Contributed-under: TianoCore Contribution Agreement 1.0
---
- %Lu is available now in format strings, for printing UINT64 values in
decimal
OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf | 2 ++
OvmfPkg/PciHostBridgeDxe/PciHostBridge.c | 22 +++++++++++++++++++-
2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf b/OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
index 40f4c3c..ca760b5 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
@@ -26,6 +26,7 @@ [Defines]
[Packages]
MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
[LibraryClasses]
UefiDriverEntryPoint
@@ -39,6 +40,7 @@ [LibraryClasses]
DevicePathLib
IoLib
PciLib
+ QemuFwCfgLib
[Sources]
PciHostBridge.c
diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
index 3486644..efef2ed 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
@@ -15,6 +15,8 @@
**/
+#include <Library/QemuFwCfgLib.h>
+
#include "PciHostBridge.h"
STATIC
@@ -207,6 +209,9 @@ InitializePciHostBridge (
)
{
EFI_STATUS Status;
+ FIRMWARE_CONFIG_ITEM FwCfgItem;
+ UINTN FwCfgSize;
+ UINT64 ExtraRootBridgesLeft;
UINTN LastRootBridgeNumber;
UINTN RootBridgeNumber;
PCI_HOST_BRIDGE_INSTANCE *HostBridge;
@@ -237,6 +242,20 @@ InitializePciHostBridge (
}
//
+ // QEMU provides the number of extra root buses, shortening the exhaustive
+ // search below. If there is no hint, the feature is missing.
+ //
+ Status = QemuFwCfgFindFile ("etc/extra-pci-roots", &FwCfgItem, &FwCfgSize);
+ if (EFI_ERROR (Status) || FwCfgSize != sizeof ExtraRootBridgesLeft) {
+ ExtraRootBridgesLeft = 0;
+ } else {
+ QemuFwCfgSelectItem (FwCfgItem);
+ QemuFwCfgReadBytes (FwCfgSize, &ExtraRootBridgesLeft);
+ DEBUG ((EFI_D_INFO, "%a: %Lu extra root buses reported by QEMU\n",
+ __FUNCTION__, ExtraRootBridgesLeft));
+ }
+
+ //
// The "main" root bus is always there.
//
LastRootBridgeNumber = 0;
@@ -247,7 +266,7 @@ InitializePciHostBridge (
// alive.
//
for (RootBridgeNumber = 1;
- RootBridgeNumber < 256;
+ RootBridgeNumber < 256 && ExtraRootBridgesLeft > 0;
++RootBridgeNumber) {
UINTN Device;
@@ -271,6 +290,7 @@ InitializePciHostBridge (
}
InsertTailList (&HostBridge->Head, &RootBus->Link);
LastRootBridgeNumber = RootBridgeNumber;
+ --ExtraRootBridgesLeft;
}
}
--
1.8.3.1
Laszlo Ersek
2015-07-08 09:20:45 UTC
Permalink
Post by Jordan Justen
Post by Laszlo Ersek
QEMU provides an fw_cfg file called "etc/extra-pci-roots", containing a
How long were the extra roots in qemu without the fw_cfg entry?
Not at all. Please see QEMU commit 2118196bb. That patch, adding the
fw_cfg file, is an integral part of Marcel's patch series that
implements the QEMU feature.

OVMF support required twelve more QEMU patches from me. See their list in:

https://bugzilla.redhat.com/show_bug.cgi?id=1193080#c12
https://bugzilla.redhat.com/show_bug.cgi?id=1193080#c11

But both Marcel's feature patches (one of which is 2118196bb), and my
tweaks for OVMF, will be part of QEMU v2.4.0.
Post by Jordan Justen
That's a leading question for, what if we only were to only scan for
the roots if the fw_cfg entry is present?
That's exactly what the patch does. (Apologies if the commit message is
not fully precise on this.) Please see the code that I'm marking below.
Post by Jordan Justen
Does seabios scan up to 255 if the fw_cfg entry is not found?
It does not, please see seabios commit 5cc7eece. And we're actually
following suit, please see below.
Post by Jordan Justen
-Jordan
Post by Laszlo Ersek
little-endian UINT64 value that exposes the number of extra root buses. We
can use this value to terminate the scan as soon as we find the last extra
root bus.
Contributed-under: TianoCore Contribution Agreement 1.0
---
- %Lu is available now in format strings, for printing UINT64 values in
decimal
OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf | 2 ++
OvmfPkg/PciHostBridgeDxe/PciHostBridge.c | 22 +++++++++++++++++++-
2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf b/OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
index 40f4c3c..ca760b5 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
@@ -26,6 +26,7 @@ [Defines]
[Packages]
MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
[LibraryClasses]
UefiDriverEntryPoint
@@ -39,6 +40,7 @@ [LibraryClasses]
DevicePathLib
IoLib
PciLib
+ QemuFwCfgLib
[Sources]
PciHostBridge.c
diff --git a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
index 3486644..efef2ed 100644
--- a/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
+++ b/OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
@@ -15,6 +15,8 @@
**/
+#include <Library/QemuFwCfgLib.h>
+
#include "PciHostBridge.h"
STATIC
@@ -207,6 +209,9 @@ InitializePciHostBridge (
)
{
EFI_STATUS Status;
+ FIRMWARE_CONFIG_ITEM FwCfgItem;
+ UINTN FwCfgSize;
+ UINT64 ExtraRootBridgesLeft;
UINTN LastRootBridgeNumber;
UINTN RootBridgeNumber;
PCI_HOST_BRIDGE_INSTANCE *HostBridge;
@@ -237,6 +242,20 @@ InitializePciHostBridge (
}
//
+ // QEMU provides the number of extra root buses, shortening the exhaustive
+ // search below. If there is no hint, the feature is missing.
+ //
+ Status = QemuFwCfgFindFile ("etc/extra-pci-roots", &FwCfgItem, &FwCfgSize);
+ if (EFI_ERROR (Status) || FwCfgSize != sizeof ExtraRootBridgesLeft) {
+ ExtraRootBridgesLeft = 0;
If QemuFwCfgFindFile() doesn't find the fw_cfg file, then it returns
Post by Jordan Justen
Post by Laszlo Ersek
+ } else {
+ QemuFwCfgSelectItem (FwCfgItem);
+ QemuFwCfgReadBytes (FwCfgSize, &ExtraRootBridgesLeft);
+ DEBUG ((EFI_D_INFO, "%a: %Lu extra root buses reported by QEMU\n",
+ __FUNCTION__, ExtraRootBridgesLeft));
+ }
+
+ //
// The "main" root bus is always there.
//
LastRootBridgeNumber = 0;
@@ -247,7 +266,7 @@ InitializePciHostBridge (
// alive.
//
for (RootBridgeNumber = 1;
- RootBridgeNumber < 256;
+ RootBridgeNumber < 256 && ExtraRootBridgesLeft > 0;
this condition here will prevent the loop body from executing even once.

See also the comment a bit higher up: "If there is no hint, the feature
is missing.".

... If you are otherwise okay with this patch, I can append a remark
like this to the commit message, before committing the set:

If the "etc/extra-pci-roots" fw_cfg file is absent, then no extra
root buses are available, and we skip the scan altogether.

Thanks!
Laszlo
Post by Jordan Justen
Post by Laszlo Ersek
++RootBridgeNumber) {
UINTN Device;
@@ -271,6 +290,7 @@ InitializePciHostBridge (
}
InsertTailList (&HostBridge->Head, &RootBus->Link);
LastRootBridgeNumber = RootBridgeNumber;
+ --ExtraRootBridgesLeft;
}
}
--
1.8.3.1
Jordan Justen
2015-07-13 18:22:25 UTC
Permalink
Post by Laszlo Ersek
Post by Laszlo Ersek
//
+ // QEMU provides the number of extra root buses, shortening the exhaustive
+ // search below. If there is no hint, the feature is missing.
+ //
+ Status = QemuFwCfgFindFile ("etc/extra-pci-roots", &FwCfgItem, &FwCfgSize);
+ if (EFI_ERROR (Status) || FwCfgSize != sizeof ExtraRootBridgesLeft) {
+ ExtraRootBridgesLeft = 0;
If QemuFwCfgFindFile() doesn't find the fw_cfg file, then it returns
Post by Laszlo Ersek
+ } else {
+ QemuFwCfgSelectItem (FwCfgItem);
+ QemuFwCfgReadBytes (FwCfgSize, &ExtraRootBridgesLeft);
+ DEBUG ((EFI_D_INFO, "%a: %Lu extra root buses reported by QEMU\n",
+ __FUNCTION__, ExtraRootBridgesLeft));
+ }
+
+ //
// The "main" root bus is always there.
//
LastRootBridgeNumber = 0;
@@ -247,7 +266,7 @@ InitializePciHostBridge (
// alive.
//
for (RootBridgeNumber = 1;
- RootBridgeNumber < 256;
+ RootBridgeNumber < 256 && ExtraRootBridgesLeft > 0;
this condition here will prevent the loop body from executing even once.
Ok. Yeah, that looks good.

20-21 Reviewed-by: Jordan Justen <***@intel.com>
Laszlo Ersek
2015-07-07 15:09:25 UTC
Permalink
The OFW device path that QEMU exports in the "bootorder" fw_cfg file, for
a device that is plugged into the main PCI root bus, is:

/***@i0cf8/...

Whereas the same device plugged into the N'th extra root bus results in:

/***@i0cf8,N/pci-***@0/...

(N is in hex.)

Extend TranslatePciOfwNodes() so that it not assume a single PCI root;
instead it parse the extra root bus serial number if present, and resolve
it in the translation to the UEFI devpath fragment.

Note that the "pci-***@0" node is a characteristic of QEMU's PXB
device. It reflects the actual emulated PCI hierarchy. We don't parse it
specifically in this patch, because it is automatically handled by the
bridge sequence translator added recently in SVN rev 17385 (git commit
feca17fa4b) -- "OvmfPkg: QemuBootOrderLib: parse OFW device path nodes of
PCI bridges".

The macro EXAMINED_OFW_NODES need not be raised from 6. The longest OFW
device paths that we wish to recognize under this new scheme comprise 5
nodes. The initial "extra root bus" OFW fragment, visible at the top,
takes up 2 nodes, after which the longest device-specific patterns (IDE
disk, IDE CD-ROM, ISA floppy, virtio-scsi disk) take 3 more nodes each.

Cc: Jordan Justen <***@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
---

Notes:
v3:
- updated to the most recently agreed upon OFW notation for extra root
buses

v2:
- new in v2

OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c | 152 ++++++++++++++++----
1 file changed, 128 insertions(+), 24 deletions(-)

diff --git a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
index 276d675..2e96343 100644
--- a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
+++ b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
@@ -27,6 +27,7 @@
#include <Guid/GlobalVariable.h>
#include <Guid/VirtioMmioTransport.h>

+#include "ExtraRootBusMap.h"

/**
OpenFirmware to UEFI device path translation output buffer size in CHAR16's.
@@ -556,6 +557,11 @@ ParseOfwNode (

@param[in] NumNodes Number of elements in OfwNode.

+ @param[in] ExtraPciRoots An EXTRA_ROOT_BUS_MAP object created with
+ CreateExtraRootBusMap(), to be used for
+ translating positions of extra root buses to
+ bus numbers.
+
@param[out] Translated Destination array receiving the UEFI path
fragment, allocated by the caller. If the
return value differs from RETURN_SUCCESS, its
@@ -576,16 +582,23 @@ ParseOfwNode (
@retval RETURN_UNSUPPORTED The array of OpenFirmware device nodes can't
be translated in the current implementation.

+ @retval RETURN_PROTOCOL_ERROR The initial OpenFirmware node refers to an
+ extra PCI root bus (by serial number) that
+ is invalid according to ExtraPciRoots.
+
**/
STATIC
RETURN_STATUS
TranslatePciOfwNodes (
- IN CONST OFW_NODE *OfwNode,
- IN UINTN NumNodes,
- OUT CHAR16 *Translated,
- IN OUT UINTN *TranslatedSize
+ IN CONST OFW_NODE *OfwNode,
+ IN UINTN NumNodes,
+ IN CONST EXTRA_ROOT_BUS_MAP *ExtraPciRoots,
+ OUT CHAR16 *Translated,
+ IN OUT UINTN *TranslatedSize
)
{
+ UINT32 PciRoot;
+ CHAR8 *Comma;
UINTN FirstNonBridge;
CHAR16 Bridges[BRIDGE_TRANSLATION_OUTPUT_SIZE];
UINTN BridgesLen;
@@ -594,7 +607,17 @@ TranslatePciOfwNodes (
UINTN Written;

//
- // Get PCI device and optional PCI function. Assume a single PCI root.
+ // Resolve the PCI root bus number.
+ //
+ // The initial OFW node for the main root bus (ie. bus number 0) is:
+ //
+ // /***@i0cf8
+ //
+ // For extra root buses, the initial OFW node is
+ //
+ // /***@i0cf8,4
+ // ^
+ // root bus serial number (not PCI bus number)
//
if (NumNodes < REQUIRED_PCI_OFW_NODES ||
!SubstringEq (OfwNode[0].DriverName, "pci")
@@ -602,6 +625,35 @@ TranslatePciOfwNodes (
return RETURN_UNSUPPORTED;
}

+ PciRoot = 0;
+ Comma = ScanMem8 (OfwNode[0].UnitAddress.Ptr, OfwNode[0].UnitAddress.Len,
+ ',');
+ if (Comma != NULL) {
+ SUBSTRING PciRootSerialSubString;
+ UINT64 PciRootSerial;
+
+ //
+ // Parse the root bus serial number from the unit address after the comma.
+ //
+ PciRootSerialSubString.Ptr = Comma + 1;
+ PciRootSerialSubString.Len = OfwNode[0].UnitAddress.Len -
+ (PciRootSerialSubString.Ptr -
+ OfwNode[0].UnitAddress.Ptr);
+ NumEntries = 1;
+ if (RETURN_ERROR (ParseUnitAddressHexList (PciRootSerialSubString,
+ &PciRootSerial, &NumEntries))) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // Map the extra root bus's serial number to its actual bus number.
+ //
+ if (EFI_ERROR (MapRootBusPosToBusNr (ExtraPciRoots, PciRootSerial,
+ &PciRoot))) {
+ return RETURN_PROTOCOL_ERROR;
+ }
+ }
+
//
// Translate a sequence of PCI bridges. For each bridge, the OFW node is:
//
@@ -709,7 +761,8 @@ TranslatePciOfwNodes (
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)/Ata(%a,%a,0x0)",
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)/Ata(%a,%a,0x0)",
+ PciRoot,
Bridges,
PciDevFun[0],
PciDevFun[1],
@@ -753,7 +806,8 @@ TranslatePciOfwNodes (
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)/Floppy(0x%Lx)",
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)/Floppy(0x%Lx)",
+ PciRoot,
Bridges,
PciDevFun[0],
PciDevFun[1],
@@ -781,7 +835,8 @@ TranslatePciOfwNodes (
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)/HD(",
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)/HD(",
+ PciRoot,
Bridges,
PciDevFun[0],
PciDevFun[1]
@@ -825,7 +880,8 @@ TranslatePciOfwNodes (
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)/Scsi(0x%Lx,0x%Lx)",
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)/Scsi(0x%Lx,0x%Lx)",
+ PciRoot,
Bridges,
PciDevFun[0],
PciDevFun[1],
@@ -849,7 +905,8 @@ TranslatePciOfwNodes (
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)",
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)",
+ PciRoot,
Bridges,
PciDevFun[0],
PciDevFun[1]
@@ -1057,6 +1114,11 @@ TranslateMmioOfwNodes (

@param[in] NumNodes Number of elements in OfwNode.

+ @param[in] ExtraPciRoots An EXTRA_ROOT_BUS_MAP object created with
+ CreateExtraRootBusMap(), to be used for
+ translating positions of extra root buses to
+ bus numbers.
+
@param[out] Translated Destination array receiving the UEFI path
fragment, allocated by the caller. If the
return value differs from RETURN_SUCCESS, its
@@ -1077,14 +1139,19 @@ TranslateMmioOfwNodes (
@retval RETURN_UNSUPPORTED The array of OpenFirmware device nodes can't
be translated in the current implementation.

+ @retval RETURN_PROTOCOL_ERROR The array of OpenFirmware device nodes has
+ been (partially) recognized, but it contains
+ a logic error / doesn't match system state.
+
**/
STATIC
RETURN_STATUS
TranslateOfwNodes (
- IN CONST OFW_NODE *OfwNode,
- IN UINTN NumNodes,
- OUT CHAR16 *Translated,
- IN OUT UINTN *TranslatedSize
+ IN CONST OFW_NODE *OfwNode,
+ IN UINTN NumNodes,
+ IN CONST EXTRA_ROOT_BUS_MAP *ExtraPciRoots,
+ OUT CHAR16 *Translated,
+ IN OUT UINTN *TranslatedSize
)
{
RETURN_STATUS Status;
@@ -1092,8 +1159,8 @@ TranslateOfwNodes (
Status = RETURN_UNSUPPORTED;

if (FeaturePcdGet (PcdQemuBootOrderPciTranslation)) {
- Status = TranslatePciOfwNodes (OfwNode, NumNodes, Translated,
- TranslatedSize);
+ Status = TranslatePciOfwNodes (OfwNode, NumNodes, ExtraPciRoots,
+ Translated, TranslatedSize);
}
if (Status == RETURN_UNSUPPORTED &&
FeaturePcdGet (PcdQemuBootOrderMmioTranslation)) {
@@ -1117,6 +1184,11 @@ TranslateOfwNodes (
characters. In other error cases, it points to
the byte that caused the error.

+ @param[in] ExtraPciRoots An EXTRA_ROOT_BUS_MAP object created with
+ CreateExtraRootBusMap(), to be used for
+ translating positions of extra root buses to
+ bus numbers.
+
@param[out] Translated Destination array receiving the UEFI path
fragment, allocated by the caller. If the
return value differs from RETURN_SUCCESS, its
@@ -1142,6 +1214,12 @@ TranslateOfwNodes (
the current implementation. Further calls
to this function are possible.

+ @retval RETURN_PROTOCOL_ERROR The OpenFirmware device path has been
+ (partially) recognized, but it contains a
+ logic error / doesn't match system state.
+ Further calls to this function are
+ possible.
+
@retval RETURN_NOT_FOUND Translation terminated. On input, *Ptr was
pointing to the empty string or "HALT". On
output, *Ptr points to the empty string
@@ -1154,9 +1232,10 @@ TranslateOfwNodes (
STATIC
RETURN_STATUS
TranslateOfwPath (
- IN OUT CONST CHAR8 **Ptr,
- OUT CHAR16 *Translated,
- IN OUT UINTN *TranslatedSize
+ IN OUT CONST CHAR8 **Ptr,
+ IN CONST EXTRA_ROOT_BUS_MAP *ExtraPciRoots,
+ OUT CHAR16 *Translated,
+ IN OUT UINTN *TranslatedSize
)
{
UINTN NumNodes;
@@ -1204,6 +1283,7 @@ TranslateOfwPath (
Status = TranslateOfwNodes (
Node,
NumNodes < EXAMINED_OFW_NODES ? NumNodes : EXAMINED_OFW_NODES,
+ ExtraPciRoots,
Translated,
TranslatedSize);
switch (Status) {
@@ -1219,6 +1299,11 @@ TranslateOfwPath (
DEBUG ((DEBUG_VERBOSE, "%a: unsupported\n", __FUNCTION__));
break;

+ case RETURN_PROTOCOL_ERROR:
+ DEBUG ((DEBUG_VERBOSE, "%a: logic error / system state mismatch\n",
+ __FUNCTION__));
+ break;
+
default:
ASSERT (0);
}
@@ -1512,6 +1597,8 @@ SetBootOrderFromQemu (
ACTIVE_OPTION *ActiveOption;
UINTN ActiveCount;

+ EXTRA_ROOT_BUS_MAP *ExtraPciRoots;
+
UINTN TranslatedSize;
CHAR16 Translated[TRANSLATION_OUTPUT_SIZE];

@@ -1556,13 +1643,24 @@ SetBootOrderFromQemu (
goto ErrorFreeBootOrder;
}

+ if (FeaturePcdGet (PcdQemuBootOrderPciTranslation)) {
+ Status = CreateExtraRootBusMap (&ExtraPciRoots);
+ if (EFI_ERROR (Status)) {
+ goto ErrorFreeActiveOption;
+ }
+ } else {
+ ExtraPciRoots = NULL;
+ }
+
//
// translate each OpenFirmware path
//
TranslatedSize = sizeof (Translated) / sizeof (Translated[0]);
- Status = TranslateOfwPath (&FwCfgPtr, Translated, &TranslatedSize);
+ Status = TranslateOfwPath (&FwCfgPtr, ExtraPciRoots, Translated,
+ &TranslatedSize);
while (Status == RETURN_SUCCESS ||
Status == RETURN_UNSUPPORTED ||
+ Status == RETURN_PROTOCOL_ERROR ||
Status == RETURN_BUFFER_TOO_SMALL) {
if (Status == RETURN_SUCCESS) {
UINTN Idx;
@@ -1582,7 +1680,7 @@ SetBootOrderFromQemu (
//
Status = BootOrderAppend (&BootOrder, &ActiveOption[Idx]);
if (Status != RETURN_SUCCESS) {
- goto ErrorFreeActiveOption;
+ goto ErrorFreeExtraPciRoots;
}
break;
}
@@ -1590,7 +1688,8 @@ SetBootOrderFromQemu (
} // translation successful

TranslatedSize = sizeof (Translated) / sizeof (Translated[0]);
- Status = TranslateOfwPath (&FwCfgPtr, Translated, &TranslatedSize);
+ Status = TranslateOfwPath (&FwCfgPtr, ExtraPciRoots, Translated,
+ &TranslatedSize);
} // scanning of OpenFirmware paths done

if (Status == RETURN_NOT_FOUND && BootOrder.Produced > 0) {
@@ -1601,7 +1700,7 @@ SetBootOrderFromQemu (
//
Status = BootOrderComplete (&BootOrder, ActiveOption, ActiveCount);
if (RETURN_ERROR (Status)) {
- goto ErrorFreeActiveOption;
+ goto ErrorFreeExtraPciRoots;
}

//
@@ -1619,13 +1718,18 @@ SetBootOrderFromQemu (
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: setting BootOrder: %r\n", __FUNCTION__, Status));
- goto ErrorFreeActiveOption;
+ goto ErrorFreeExtraPciRoots;
}

DEBUG ((DEBUG_INFO, "%a: setting BootOrder: success\n", __FUNCTION__));
PruneBootVariables (ActiveOption, ActiveCount);
}

+ErrorFreeExtraPciRoots:
+ if (ExtraPciRoots != NULL) {
+ DestroyExtraRootBusMap (ExtraPciRoots);
+ }
+
ErrorFreeActiveOption:
FreePool (ActiveOption);
--
1.8.3.1
Jordan Justen
2015-07-13 23:18:06 UTC
Permalink
Post by Laszlo Ersek
The OFW device path that QEMU exports in the "bootorder" fw_cfg file, for
(N is in hex.)
Extend TranslatePciOfwNodes() so that it not assume a single PCI root;
instead it parse the extra root bus serial number if present, and resolve
it in the translation to the UEFI devpath fragment.
device. It reflects the actual emulated PCI hierarchy. We don't parse it
specifically in this patch, because it is automatically handled by the
bridge sequence translator added recently in SVN rev 17385 (git commit
feca17fa4b) -- "OvmfPkg: QemuBootOrderLib: parse OFW device path nodes of
PCI bridges".
The macro EXAMINED_OFW_NODES need not be raised from 6. The longest OFW
device paths that we wish to recognize under this new scheme comprise 5
nodes. The initial "extra root bus" OFW fragment, visible at the top,
takes up 2 nodes, after which the longest device-specific patterns (IDE
disk, IDE CD-ROM, ISA floppy, virtio-scsi disk) take 3 more nodes each.
Contributed-under: TianoCore Contribution Agreement 1.0
---
- updated to the most recently agreed upon OFW notation for extra root
buses
- new in v2
OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c | 152 ++++++++++++++++----
1 file changed, 128 insertions(+), 24 deletions(-)
diff --git a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
index 276d675..2e96343 100644
--- a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
+++ b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
@@ -27,6 +27,7 @@
#include <Guid/GlobalVariable.h>
#include <Guid/VirtioMmioTransport.h>
+#include "ExtraRootBusMap.h"
/**
OpenFirmware to UEFI device path translation output buffer size in CHAR16's.
@@ -556,6 +557,11 @@ ParseOfwNode (
@param[in] NumNodes Number of elements in OfwNode.
+ CreateExtraRootBusMap(), to be used for
+ translating positions of extra root buses to
+ bus numbers.
+
@param[out] Translated Destination array receiving the UEFI path
fragment, allocated by the caller. If the
return value differs from RETURN_SUCCESS, its
@@ -576,16 +582,23 @@ ParseOfwNode (
@retval RETURN_UNSUPPORTED The array of OpenFirmware device nodes can't
be translated in the current implementation.
+ extra PCI root bus (by serial number) that
+ is invalid according to ExtraPciRoots.
+
**/
STATIC
RETURN_STATUS
TranslatePciOfwNodes (
- IN CONST OFW_NODE *OfwNode,
- IN UINTN NumNodes,
- OUT CHAR16 *Translated,
- IN OUT UINTN *TranslatedSize
+ IN CONST OFW_NODE *OfwNode,
+ IN UINTN NumNodes,
+ IN CONST EXTRA_ROOT_BUS_MAP *ExtraPciRoots,
+ OUT CHAR16 *Translated,
+ IN OUT UINTN *TranslatedSize
)
{
+ UINT32 PciRoot;
+ CHAR8 *Comma;
UINTN FirstNonBridge;
CHAR16 Bridges[BRIDGE_TRANSLATION_OUTPUT_SIZE];
UINTN BridgesLen;
@@ -594,7 +607,17 @@ TranslatePciOfwNodes (
UINTN Written;
//
- // Get PCI device and optional PCI function. Assume a single PCI root.
+ // Resolve the PCI root bus number.
+ //
+ //
+ //
+ // For extra root buses, the initial OFW node is
+ //
+ // ^
+ // root bus serial number (not PCI bus number)
//
if (NumNodes < REQUIRED_PCI_OFW_NODES ||
!SubstringEq (OfwNode[0].DriverName, "pci")
@@ -602,6 +625,35 @@ TranslatePciOfwNodes (
return RETURN_UNSUPPORTED;
}
+ PciRoot = 0;
+ Comma = ScanMem8 (OfwNode[0].UnitAddress.Ptr, OfwNode[0].UnitAddress.Len,
+ ',');
+ if (Comma != NULL) {
+ SUBSTRING PciRootSerialSubString;
+ UINT64 PciRootSerial;
+
+ //
+ // Parse the root bus serial number from the unit address after the comma.
+ //
+ PciRootSerialSubString.Ptr = Comma + 1;
+ PciRootSerialSubString.Len = OfwNode[0].UnitAddress.Len -
+ (PciRootSerialSubString.Ptr -
+ OfwNode[0].UnitAddress.Ptr);
+ NumEntries = 1;
+ if (RETURN_ERROR (ParseUnitAddressHexList (PciRootSerialSubString,
+ &PciRootSerial, &NumEntries))) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // Map the extra root bus's serial number to its actual bus number.
+ //
+ if (EFI_ERROR (MapRootBusPosToBusNr (ExtraPciRoots, PciRootSerial,
+ &PciRoot))) {
+ return RETURN_PROTOCOL_ERROR;
+ }
+ }
+
//
//
@@ -709,7 +761,8 @@ TranslatePciOfwNodes (
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)/Ata(%a,%a,0x0)",
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)/Ata(%a,%a,0x0)",
+ PciRoot,
Bridges,
PciDevFun[0],
PciDevFun[1],
@@ -753,7 +806,8 @@ TranslatePciOfwNodes (
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)/Floppy(0x%Lx)",
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)/Floppy(0x%Lx)",
+ PciRoot,
Bridges,
PciDevFun[0],
PciDevFun[1],
@@ -781,7 +835,8 @@ TranslatePciOfwNodes (
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)/HD(",
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)/HD(",
+ PciRoot,
Bridges,
PciDevFun[0],
PciDevFun[1]
@@ -825,7 +880,8 @@ TranslatePciOfwNodes (
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)/Scsi(0x%Lx,0x%Lx)",
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)/Scsi(0x%Lx,0x%Lx)",
+ PciRoot,
Bridges,
PciDevFun[0],
PciDevFun[1],
@@ -849,7 +905,8 @@ TranslatePciOfwNodes (
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)",
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)",
+ PciRoot,
Bridges,
PciDevFun[0],
PciDevFun[1]
@@ -1057,6 +1114,11 @@ TranslateMmioOfwNodes (
@param[in] NumNodes Number of elements in OfwNode.
+ CreateExtraRootBusMap(), to be used for
+ translating positions of extra root buses to
+ bus numbers.
+
@param[out] Translated Destination array receiving the UEFI path
fragment, allocated by the caller. If the
return value differs from RETURN_SUCCESS, its
@@ -1077,14 +1139,19 @@ TranslateMmioOfwNodes (
@retval RETURN_UNSUPPORTED The array of OpenFirmware device nodes can't
be translated in the current implementation.
+ been (partially) recognized, but it contains
+ a logic error / doesn't match system state.
+
**/
STATIC
RETURN_STATUS
TranslateOfwNodes (
- IN CONST OFW_NODE *OfwNode,
- IN UINTN NumNodes,
- OUT CHAR16 *Translated,
- IN OUT UINTN *TranslatedSize
+ IN CONST OFW_NODE *OfwNode,
+ IN UINTN NumNodes,
+ IN CONST EXTRA_ROOT_BUS_MAP *ExtraPciRoots,
+ OUT CHAR16 *Translated,
+ IN OUT UINTN *TranslatedSize
)
{
RETURN_STATUS Status;
@@ -1092,8 +1159,8 @@ TranslateOfwNodes (
Status = RETURN_UNSUPPORTED;
if (FeaturePcdGet (PcdQemuBootOrderPciTranslation)) {
- Status = TranslatePciOfwNodes (OfwNode, NumNodes, Translated,
- TranslatedSize);
+ Status = TranslatePciOfwNodes (OfwNode, NumNodes, ExtraPciRoots,
+ Translated, TranslatedSize);
}
if (Status == RETURN_UNSUPPORTED &&
FeaturePcdGet (PcdQemuBootOrderMmioTranslation)) {
@@ -1117,6 +1184,11 @@ TranslateOfwNodes (
characters. In other error cases, it points to
the byte that caused the error.
+ CreateExtraRootBusMap(), to be used for
+ translating positions of extra root buses to
+ bus numbers.
+
@param[out] Translated Destination array receiving the UEFI path
fragment, allocated by the caller. If the
return value differs from RETURN_SUCCESS, its
@@ -1142,6 +1214,12 @@ TranslateOfwNodes (
the current implementation. Further calls
to this function are possible.
+ (partially) recognized, but it contains a
+ logic error / doesn't match system state.
+ Further calls to this function are
+ possible.
+
@retval RETURN_NOT_FOUND Translation terminated. On input, *Ptr was
pointing to the empty string or "HALT". On
output, *Ptr points to the empty string
@@ -1154,9 +1232,10 @@ TranslateOfwNodes (
STATIC
RETURN_STATUS
TranslateOfwPath (
- IN OUT CONST CHAR8 **Ptr,
- OUT CHAR16 *Translated,
- IN OUT UINTN *TranslatedSize
+ IN OUT CONST CHAR8 **Ptr,
+ IN CONST EXTRA_ROOT_BUS_MAP *ExtraPciRoots,
+ OUT CHAR16 *Translated,
+ IN OUT UINTN *TranslatedSize
)
{
UINTN NumNodes;
@@ -1204,6 +1283,7 @@ TranslateOfwPath (
Status = TranslateOfwNodes (
Node,
NumNodes < EXAMINED_OFW_NODES ? NumNodes : EXAMINED_OFW_NODES,
+ ExtraPciRoots,
Translated,
TranslatedSize);
switch (Status) {
@@ -1219,6 +1299,11 @@ TranslateOfwPath (
DEBUG ((DEBUG_VERBOSE, "%a: unsupported\n", __FUNCTION__));
break;
+ DEBUG ((DEBUG_VERBOSE, "%a: logic error / system state mismatch\n",
+ __FUNCTION__));
+ break;
+
ASSERT (0);
}
@@ -1512,6 +1597,8 @@ SetBootOrderFromQemu (
ACTIVE_OPTION *ActiveOption;
UINTN ActiveCount;
+ EXTRA_ROOT_BUS_MAP *ExtraPciRoots;
+
UINTN TranslatedSize;
CHAR16 Translated[TRANSLATION_OUTPUT_SIZE];
@@ -1556,13 +1643,24 @@ SetBootOrderFromQemu (
goto ErrorFreeBootOrder;
}
+ if (FeaturePcdGet (PcdQemuBootOrderPciTranslation)) {
+ Status = CreateExtraRootBusMap (&ExtraPciRoots);
+ if (EFI_ERROR (Status)) {
+ goto ErrorFreeActiveOption;
+ }
+ } else {
+ ExtraPciRoots = NULL;
+ }
+
//
// translate each OpenFirmware path
//
TranslatedSize = sizeof (Translated) / sizeof (Translated[0]);
- Status = TranslateOfwPath (&FwCfgPtr, Translated, &TranslatedSize);
+ Status = TranslateOfwPath (&FwCfgPtr, ExtraPciRoots, Translated,
+ &TranslatedSize);
while (Status == RETURN_SUCCESS ||
Status == RETURN_UNSUPPORTED ||
+ Status == RETURN_PROTOCOL_ERROR ||
Status == RETURN_BUFFER_TOO_SMALL) {
if (Status == RETURN_SUCCESS) {
UINTN Idx;
@@ -1582,7 +1680,7 @@ SetBootOrderFromQemu (
//
Status = BootOrderAppend (&BootOrder, &ActiveOption[Idx]);
if (Status != RETURN_SUCCESS) {
- goto ErrorFreeActiveOption;
+ goto ErrorFreeExtraPciRoots;
}
break;
}
@@ -1590,7 +1688,8 @@ SetBootOrderFromQemu (
} // translation successful
TranslatedSize = sizeof (Translated) / sizeof (Translated[0]);
- Status = TranslateOfwPath (&FwCfgPtr, Translated, &TranslatedSize);
+ Status = TranslateOfwPath (&FwCfgPtr, ExtraPciRoots, Translated,
+ &TranslatedSize);
} // scanning of OpenFirmware paths done
if (Status == RETURN_NOT_FOUND && BootOrder.Produced > 0) {
@@ -1601,7 +1700,7 @@ SetBootOrderFromQemu (
//
Status = BootOrderComplete (&BootOrder, ActiveOption, ActiveCount);
if (RETURN_ERROR (Status)) {
- goto ErrorFreeActiveOption;
+ goto ErrorFreeExtraPciRoots;
}
//
@@ -1619,13 +1718,18 @@ SetBootOrderFromQemu (
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: setting BootOrder: %r\n", __FUNCTION__, Status));
- goto ErrorFreeActiveOption;
+ goto ErrorFreeExtraPciRoots;
}
DEBUG ((DEBUG_INFO, "%a: setting BootOrder: success\n", __FUNCTION__));
PruneBootVariables (ActiveOption, ActiveCount);
}
+ if (ExtraPciRoots != NULL) {
+ DestroyExtraRootBusMap (ExtraPciRoots);
+ }
+
FreePool (ActiveOption);
--
1.8.3.1
Laszlo Ersek
2015-07-14 12:08:24 UTC
Permalink
Greatly appreciated!

I committed the series to SVN as r17943 through r17965, inclusive.

Now back to the end-of-dxe series... :)

Thanks!
Laszlo
Post by Laszlo Ersek
The OFW device path that QEMU exports in the "bootorder" fw_cfg file, for
(N is in hex.)
Extend TranslatePciOfwNodes() so that it not assume a single PCI root;
instead it parse the extra root bus serial number if present, and resolve
it in the translation to the UEFI devpath fragment.
device. It reflects the actual emulated PCI hierarchy. We don't parse it
specifically in this patch, because it is automatically handled by the
bridge sequence translator added recently in SVN rev 17385 (git commit
feca17fa4b) -- "OvmfPkg: QemuBootOrderLib: parse OFW device path nodes of
PCI bridges".
The macro EXAMINED_OFW_NODES need not be raised from 6. The longest OFW
device paths that we wish to recognize under this new scheme comprise 5
nodes. The initial "extra root bus" OFW fragment, visible at the top,
takes up 2 nodes, after which the longest device-specific patterns (IDE
disk, IDE CD-ROM, ISA floppy, virtio-scsi disk) take 3 more nodes each.
Contributed-under: TianoCore Contribution Agreement 1.0
---
- updated to the most recently agreed upon OFW notation for extra root
buses
- new in v2
OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c | 152 ++++++++++++++++----
1 file changed, 128 insertions(+), 24 deletions(-)
diff --git a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
index 276d675..2e96343 100644
--- a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
+++ b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
@@ -27,6 +27,7 @@
#include <Guid/GlobalVariable.h>
#include <Guid/VirtioMmioTransport.h>
+#include "ExtraRootBusMap.h"
/**
OpenFirmware to UEFI device path translation output buffer size in CHAR16's.
@@ -556,6 +557,11 @@ ParseOfwNode (
@param[in] NumNodes Number of elements in OfwNode.
+ CreateExtraRootBusMap(), to be used for
+ translating positions of extra root buses to
+ bus numbers.
+
@param[out] Translated Destination array receiving the UEFI path
fragment, allocated by the caller. If the
return value differs from RETURN_SUCCESS, its
@@ -576,16 +582,23 @@ ParseOfwNode (
@retval RETURN_UNSUPPORTED The array of OpenFirmware device nodes can't
be translated in the current implementation.
+ extra PCI root bus (by serial number) that
+ is invalid according to ExtraPciRoots.
+
**/
STATIC
RETURN_STATUS
TranslatePciOfwNodes (
- IN CONST OFW_NODE *OfwNode,
- IN UINTN NumNodes,
- OUT CHAR16 *Translated,
- IN OUT UINTN *TranslatedSize
+ IN CONST OFW_NODE *OfwNode,
+ IN UINTN NumNodes,
+ IN CONST EXTRA_ROOT_BUS_MAP *ExtraPciRoots,
+ OUT CHAR16 *Translated,
+ IN OUT UINTN *TranslatedSize
)
{
+ UINT32 PciRoot;
+ CHAR8 *Comma;
UINTN FirstNonBridge;
CHAR16 Bridges[BRIDGE_TRANSLATION_OUTPUT_SIZE];
UINTN BridgesLen;
@@ -594,7 +607,17 @@ TranslatePciOfwNodes (
UINTN Written;
//
- // Get PCI device and optional PCI function. Assume a single PCI root.
+ // Resolve the PCI root bus number.
+ //
+ //
+ //
+ // For extra root buses, the initial OFW node is
+ //
+ // ^
+ // root bus serial number (not PCI bus number)
//
if (NumNodes < REQUIRED_PCI_OFW_NODES ||
!SubstringEq (OfwNode[0].DriverName, "pci")
@@ -602,6 +625,35 @@ TranslatePciOfwNodes (
return RETURN_UNSUPPORTED;
}
+ PciRoot = 0;
+ Comma = ScanMem8 (OfwNode[0].UnitAddress.Ptr, OfwNode[0].UnitAddress.Len,
+ ',');
+ if (Comma != NULL) {
+ SUBSTRING PciRootSerialSubString;
+ UINT64 PciRootSerial;
+
+ //
+ // Parse the root bus serial number from the unit address after the comma.
+ //
+ PciRootSerialSubString.Ptr = Comma + 1;
+ PciRootSerialSubString.Len = OfwNode[0].UnitAddress.Len -
+ (PciRootSerialSubString.Ptr -
+ OfwNode[0].UnitAddress.Ptr);
+ NumEntries = 1;
+ if (RETURN_ERROR (ParseUnitAddressHexList (PciRootSerialSubString,
+ &PciRootSerial, &NumEntries))) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // Map the extra root bus's serial number to its actual bus number.
+ //
+ if (EFI_ERROR (MapRootBusPosToBusNr (ExtraPciRoots, PciRootSerial,
+ &PciRoot))) {
+ return RETURN_PROTOCOL_ERROR;
+ }
+ }
+
//
//
@@ -709,7 +761,8 @@ TranslatePciOfwNodes (
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)/Ata(%a,%a,0x0)",
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)/Ata(%a,%a,0x0)",
+ PciRoot,
Bridges,
PciDevFun[0],
PciDevFun[1],
@@ -753,7 +806,8 @@ TranslatePciOfwNodes (
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)/Floppy(0x%Lx)",
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)/Floppy(0x%Lx)",
+ PciRoot,
Bridges,
PciDevFun[0],
PciDevFun[1],
@@ -781,7 +835,8 @@ TranslatePciOfwNodes (
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)/HD(",
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)/HD(",
+ PciRoot,
Bridges,
PciDevFun[0],
PciDevFun[1]
@@ -825,7 +880,8 @@ TranslatePciOfwNodes (
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)/Scsi(0x%Lx,0x%Lx)",
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)/Scsi(0x%Lx,0x%Lx)",
+ PciRoot,
Bridges,
PciDevFun[0],
PciDevFun[1],
@@ -849,7 +905,8 @@ TranslatePciOfwNodes (
Written = UnicodeSPrintAsciiFormat (
Translated,
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes
- "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)",
+ "PciRoot(0x%x)%s/Pci(0x%Lx,0x%Lx)",
+ PciRoot,
Bridges,
PciDevFun[0],
PciDevFun[1]
@@ -1057,6 +1114,11 @@ TranslateMmioOfwNodes (
@param[in] NumNodes Number of elements in OfwNode.
+ CreateExtraRootBusMap(), to be used for
+ translating positions of extra root buses to
+ bus numbers.
+
@param[out] Translated Destination array receiving the UEFI path
fragment, allocated by the caller. If the
return value differs from RETURN_SUCCESS, its
@@ -1077,14 +1139,19 @@ TranslateMmioOfwNodes (
@retval RETURN_UNSUPPORTED The array of OpenFirmware device nodes can't
be translated in the current implementation.
+ been (partially) recognized, but it contains
+ a logic error / doesn't match system state.
+
**/
STATIC
RETURN_STATUS
TranslateOfwNodes (
- IN CONST OFW_NODE *OfwNode,
- IN UINTN NumNodes,
- OUT CHAR16 *Translated,
- IN OUT UINTN *TranslatedSize
+ IN CONST OFW_NODE *OfwNode,
+ IN UINTN NumNodes,
+ IN CONST EXTRA_ROOT_BUS_MAP *ExtraPciRoots,
+ OUT CHAR16 *Translated,
+ IN OUT UINTN *TranslatedSize
)
{
RETURN_STATUS Status;
@@ -1092,8 +1159,8 @@ TranslateOfwNodes (
Status = RETURN_UNSUPPORTED;
if (FeaturePcdGet (PcdQemuBootOrderPciTranslation)) {
- Status = TranslatePciOfwNodes (OfwNode, NumNodes, Translated,
- TranslatedSize);
+ Status = TranslatePciOfwNodes (OfwNode, NumNodes, ExtraPciRoots,
+ Translated, TranslatedSize);
}
if (Status == RETURN_UNSUPPORTED &&
FeaturePcdGet (PcdQemuBootOrderMmioTranslation)) {
@@ -1117,6 +1184,11 @@ TranslateOfwNodes (
characters. In other error cases, it points to
the byte that caused the error.
+ CreateExtraRootBusMap(), to be used for
+ translating positions of extra root buses to
+ bus numbers.
+
@param[out] Translated Destination array receiving the UEFI path
fragment, allocated by the caller. If the
return value differs from RETURN_SUCCESS, its
@@ -1142,6 +1214,12 @@ TranslateOfwNodes (
the current implementation. Further calls
to this function are possible.
+ (partially) recognized, but it contains a
+ logic error / doesn't match system state.
+ Further calls to this function are
+ possible.
+
@retval RETURN_NOT_FOUND Translation terminated. On input, *Ptr was
pointing to the empty string or "HALT". On
output, *Ptr points to the empty string
@@ -1154,9 +1232,10 @@ TranslateOfwNodes (
STATIC
RETURN_STATUS
TranslateOfwPath (
- IN OUT CONST CHAR8 **Ptr,
- OUT CHAR16 *Translated,
- IN OUT UINTN *TranslatedSize
+ IN OUT CONST CHAR8 **Ptr,
+ IN CONST EXTRA_ROOT_BUS_MAP *ExtraPciRoots,
+ OUT CHAR16 *Translated,
+ IN OUT UINTN *TranslatedSize
)
{
UINTN NumNodes;
@@ -1204,6 +1283,7 @@ TranslateOfwPath (
Status = TranslateOfwNodes (
Node,
NumNodes < EXAMINED_OFW_NODES ? NumNodes : EXAMINED_OFW_NODES,
+ ExtraPciRoots,
Translated,
TranslatedSize);
switch (Status) {
@@ -1219,6 +1299,11 @@ TranslateOfwPath (
DEBUG ((DEBUG_VERBOSE, "%a: unsupported\n", __FUNCTION__));
break;
+ DEBUG ((DEBUG_VERBOSE, "%a: logic error / system state mismatch\n",
+ __FUNCTION__));
+ break;
+
ASSERT (0);
}
@@ -1512,6 +1597,8 @@ SetBootOrderFromQemu (
ACTIVE_OPTION *ActiveOption;
UINTN ActiveCount;
+ EXTRA_ROOT_BUS_MAP *ExtraPciRoots;
+
UINTN TranslatedSize;
CHAR16 Translated[TRANSLATION_OUTPUT_SIZE];
@@ -1556,13 +1643,24 @@ SetBootOrderFromQemu (
goto ErrorFreeBootOrder;
}
+ if (FeaturePcdGet (PcdQemuBootOrderPciTranslation)) {
+ Status = CreateExtraRootBusMap (&ExtraPciRoots);
+ if (EFI_ERROR (Status)) {
+ goto ErrorFreeActiveOption;
+ }
+ } else {
+ ExtraPciRoots = NULL;
+ }
+
//
// translate each OpenFirmware path
//
TranslatedSize = sizeof (Translated) / sizeof (Translated[0]);
- Status = TranslateOfwPath (&FwCfgPtr, Translated, &TranslatedSize);
+ Status = TranslateOfwPath (&FwCfgPtr, ExtraPciRoots, Translated,
+ &TranslatedSize);
while (Status == RETURN_SUCCESS ||
Status == RETURN_UNSUPPORTED ||
+ Status == RETURN_PROTOCOL_ERROR ||
Status == RETURN_BUFFER_TOO_SMALL) {
if (Status == RETURN_SUCCESS) {
UINTN Idx;
@@ -1582,7 +1680,7 @@ SetBootOrderFromQemu (
//
Status = BootOrderAppend (&BootOrder, &ActiveOption[Idx]);
if (Status != RETURN_SUCCESS) {
- goto ErrorFreeActiveOption;
+ goto ErrorFreeExtraPciRoots;
}
break;
}
@@ -1590,7 +1688,8 @@ SetBootOrderFromQemu (
} // translation successful
TranslatedSize = sizeof (Translated) / sizeof (Translated[0]);
- Status = TranslateOfwPath (&FwCfgPtr, Translated, &TranslatedSize);
+ Status = TranslateOfwPath (&FwCfgPtr, ExtraPciRoots, Translated,
+ &TranslatedSize);
} // scanning of OpenFirmware paths done
if (Status == RETURN_NOT_FOUND && BootOrder.Produced > 0) {
@@ -1601,7 +1700,7 @@ SetBootOrderFromQemu (
//
Status = BootOrderComplete (&BootOrder, ActiveOption, ActiveCount);
if (RETURN_ERROR (Status)) {
- goto ErrorFreeActiveOption;
+ goto ErrorFreeExtraPciRoots;
}
//
@@ -1619,13 +1718,18 @@ SetBootOrderFromQemu (
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: setting BootOrder: %r\n", __FUNCTION__, Status));
- goto ErrorFreeActiveOption;
+ goto ErrorFreeExtraPciRoots;
}
DEBUG ((DEBUG_INFO, "%a: setting BootOrder: success\n", __FUNCTION__));
PruneBootVariables (ActiveOption, ActiveCount);
}
+ if (ExtraPciRoots != NULL) {
+ DestroyExtraRootBusMap (ExtraPciRoots);
+ }
+
FreePool (ActiveOption);
--
1.8.3.1
Loading...