* [PATCH v4 0/5] MdeModulePkg: add support for non-discoverable devices
@ 2016-11-25 15:42 Ard Biesheuvel
2016-11-25 15:42 ` [PATCH v4 1/5] MdeModulePkg: introduce non-discoverable device protocol Ard Biesheuvel
` (5 more replies)
0 siblings, 6 replies; 19+ messages in thread
From: Ard Biesheuvel @ 2016-11-25 15:42 UTC (permalink / raw)
To: edk2-devel, leif.lindholm, liming.gao, afish, ruiyu.ni,
michael.d.kinney, mw, feng.tian
Cc: Ard Biesheuvel
The rationale for this series is the fact that many ARM platforms implement
some form of PCI 'emulation', to allow non-discoverable devices that implement
standardized host controller interfaces (i.e., EHCI, AHCI) to be controlled by
the generic EDK2 drivers, which are layered on top of the PCI I/O protocols
(even though the respective host controller specifications don't mandate that)
There are a couple of problems with that approach:
- Most implementations are based on the original code created for BeagleBoard,
which is a 32-bit platform. Unlike x86, which usually does not perform PCI
DMA above 4 GB, the ARM ecosystem is much more heterogeneous, and platforms
that have memory both above and below the 4 GB mark may ship with, e.g., EHCI
controllers that do not implement 64-bit DMA addressing.
- Implementations depend on the DmaLib library class in EmbeddedPkg, of which
coherent and non-coherent implementations exists. However, both types of
devices may appear on a single platform, requiring several instances of the
same driver.
- Existing implementations do not follow the UEFI driver model, but instantiate
a fixed number of PCI I/O protocol handles, and bring up all the devices when
doing so. However, the UEFI philosophy is to only instantiate (and thus
initialize) devices that are involved in booting.
So instead, let's define a base protocol that simply asserts the presence of
a certain kind of device at a certain memory offset, allowing platforms to
instantiate any number of these statically, and leave it to post-DXE driver
dispatch to actually bind the drivers as usual. This is implemented in patch #1.
Note that it includes an AMBA device type, which we intend to use in the future
to move ARM AMBA drivers to the UEFI driver model as well (i.e., LCD controller,
SD/MMC controller)
Patch #2 implements a utility library to register non-discoverable devices.
Patch #3 implements the UEFI driver that instantiates PCI I/O protocol handles
for non-discoverable devices that we know can be driven by a generic driver in
EDK2. The initial version implements coherent DMA only.
Patch #4 implements non-coherent DMA for the driver added in patch #3.
Patch #5 is included for reference. It ports the BeagleBoard platform to the
new driver stack.
Changes in v4:
- use GUIDs to describe the type of device (AHCI, EHCI, etc), rathen than en
enum, to make the protocol more flexible and futureproof
- revert special handling of SDHCI, which does not map cleanly onto a single
PCI device (SDHCI-PCI may expose several slots, each of which is a full
fledged implementation of the SDHCI spec, but the EDK2 SDHCI driver does
not model those as a bus)
- don't treat 64-bit BARs as 2 logical BARs
Branch can be found here
https://git.linaro.org/people/ard.biesheuvel/uefi-next.git/log/?h=non-discoverable-pci-v4
Changes in v3:
- Modified the base protocol to describe any number of resources using ACPI
resource descriptors. The current crop of targeted peripherals does not
require that, but it allows for much more flexibility in the future. This
also means that the MMIO region sizes are no longer hard-coded base on the
controller type (EHCI, AHCI, etc) but need to be declared when the devices
are registered.
- Update the registration library API to allow multiple MMIO regions to be
declared.
- When performing uncached allocations, record the original memory region
attributes so we can restore them correctly on free.
- Some fixes in the 4GB boundary checks for Map/Unmap
- Rename gNonDiscoverableDeviceProtocolGuid to
gEdkiiNonDiscoverableDeviceProtocolGuid
Ard Biesheuvel (5):
MdeModulePkg: introduce non-discoverable device protocol
MdeModulePkg: introduce helper library to register non-discoverable
devices
MdeModulePkg: implement generic PCI I/O driver for non-discoverable
devices
MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent
DMA
Omap35xxPkg/PciEmulation: port to new non-discoverable device
infrastructure
BeagleBoardPkg/BeagleBoardPkg.dsc | 2 +
BeagleBoardPkg/BeagleBoardPkg.fdf | 1 +
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c | 75 ++
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c | 235 +++++
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf | 54 +
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c | 1116 ++++++++++++++++++++
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h | 113 ++
MdeModulePkg/Include/Guid/NonDiscoverableDevice.h | 58 +
MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h | 62 ++
MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 77 ++
MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c | 204 ++++
MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf | 46 +
MdeModulePkg/MdeModulePkg.dec | 18 +
MdeModulePkg/MdeModulePkg.dsc | 3 +
Omap35xxPkg/Omap35xxPkg.dsc | 2 +-
Omap35xxPkg/PciEmulation/PciEmulation.c | 578 +---------
Omap35xxPkg/PciEmulation/PciEmulation.h | 292 -----
Omap35xxPkg/PciEmulation/PciEmulation.inf | 16 +-
Omap35xxPkg/PciEmulation/PciRootBridgeIo.c | 306 ------
19 files changed, 2097 insertions(+), 1161 deletions(-)
create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c
create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
create mode 100644 MdeModulePkg/Include/Guid/NonDiscoverableDevice.h
create mode 100644 MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h
create mode 100644 MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
create mode 100644 MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c
create mode 100644 MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
delete mode 100644 Omap35xxPkg/PciEmulation/PciEmulation.h
delete mode 100644 Omap35xxPkg/PciEmulation/PciRootBridgeIo.c
--
2.7.4
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v4 1/5] MdeModulePkg: introduce non-discoverable device protocol
2016-11-25 15:42 [PATCH v4 0/5] MdeModulePkg: add support for non-discoverable devices Ard Biesheuvel
@ 2016-11-25 15:42 ` Ard Biesheuvel
2016-11-28 1:57 ` Ni, Ruiyu
2016-11-25 15:42 ` [PATCH v4 2/5] MdeModulePkg: introduce helper library to register non-discoverable devices Ard Biesheuvel
` (4 subsequent siblings)
5 siblings, 1 reply; 19+ messages in thread
From: Ard Biesheuvel @ 2016-11-25 15:42 UTC (permalink / raw)
To: edk2-devel, leif.lindholm, liming.gao, afish, ruiyu.ni,
michael.d.kinney, mw, feng.tian
Cc: Ard Biesheuvel
Introduce a protocol that can be exposed by a platform for devices that
are not discoverable, usually because they are wired straight to the
memory bus rather than to an enumerable bus like PCI or USB.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
MdeModulePkg/Include/Guid/NonDiscoverableDevice.h | 58 +++++++++++++++
MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 77 ++++++++++++++++++++
MdeModulePkg/MdeModulePkg.dec | 14 ++++
3 files changed, 149 insertions(+)
diff --git a/MdeModulePkg/Include/Guid/NonDiscoverableDevice.h b/MdeModulePkg/Include/Guid/NonDiscoverableDevice.h
new file mode 100644
index 000000000000..d182e4b9d2fe
--- /dev/null
+++ b/MdeModulePkg/Include/Guid/NonDiscoverableDevice.h
@@ -0,0 +1,58 @@
+/** @file
+ GUIDs to identify devices that are not on a discoverable bus but can be
+ controlled by a standard class driver
+
+ Copyright (c) 2016, Linaro, Ltd. 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
+
+ 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 __NON_DISCOVERABLE_DEVICE_GUID_H__
+#define __NON_DISCOVERABLE_DEVICE_GUID_H__
+
+#define EDKII_NON_DISCOVERABLE_AHCI_DEVICE_GUID \
+ { 0xC7D35798, 0xE4D2, 0x4A93, {0xB1, 0x45, 0x54, 0x88, 0x9F, 0x02, 0x58, 0x4B } }
+
+#define EDKII_NON_DISCOVERABLE_AMBA_DEVICE_GUID \
+ { 0x94440339, 0xCC93, 0x4506, {0xB4, 0xC6, 0xEE, 0x8D, 0x0F, 0x4C, 0xA1, 0x91 } }
+
+#define EDKII_NON_DISCOVERABLE_EHCI_DEVICE_GUID \
+ { 0xEAEE5615, 0x0CFD, 0x45FC, {0x87, 0x69, 0xA0, 0xD8, 0x56, 0x95, 0xAF, 0x85 } }
+
+#define EDKII_NON_DISCOVERABLE_NVME_DEVICE_GUID \
+ { 0xC5F25542, 0x2A79, 0x4A26, {0x81, 0xBB, 0x4E, 0xA6, 0x32, 0x33, 0xB3, 0x09 } }
+
+#define EDKII_NON_DISCOVERABLE_OHCI_DEVICE_GUID \
+ { 0xB20005B0, 0xBB2D, 0x496F, {0x86, 0x9C, 0x23, 0x0B, 0x44, 0x79, 0xE7, 0xD1 } }
+
+#define EDKII_NON_DISCOVERABLE_SDHCI_DEVICE_GUID \
+ { 0x1DD1D619, 0xF9B8, 0x463E, {0x86, 0x81, 0xD1, 0xDC, 0x7C, 0x07, 0xB7, 0x2C } }
+
+#define EDKII_NON_DISCOVERABLE_UFS_DEVICE_GUID \
+ { 0x2EA77912, 0x80A8, 0x4947, {0xBE, 0x69, 0xCD, 0xD0, 0x0A, 0xFB, 0xE5, 0x56 } }
+
+#define EDKII_NON_DISCOVERABLE_UHCI_DEVICE_GUID \
+ { 0xA8CDA0A2, 0x4F37, 0x4A1B, {0x8E, 0x10, 0x8E, 0xF3, 0xCC, 0x3B, 0xF3, 0xA8 } }
+
+#define EDKII_NON_DISCOVERABLE_XHCI_DEVICE_GUID \
+ { 0xB1BE0BC5, 0x6C28, 0x442D, {0xAA, 0x37, 0x15, 0x1B, 0x42, 0x57, 0xBD, 0x78 } }
+
+
+extern EFI_GUID gEdkiiNonDiscoverableAhciDeviceGuid;
+extern EFI_GUID gEdkiiNonDiscoverableAmbaDeviceGuid;
+extern EFI_GUID gEdkiiNonDiscoverableEhciDeviceGuid;
+extern EFI_GUID gEdkiiNonDiscoverableNvmeDeviceGuid;
+extern EFI_GUID gEdkiiNonDiscoverableOhciDeviceGuid;
+extern EFI_GUID gEdkiiNonDiscoverableSdhciDeviceGuid;
+extern EFI_GUID gEdkiiNonDiscoverableUfsDeviceGuid;
+extern EFI_GUID gEdkiiNonDiscoverableUhciDeviceGuid;
+extern EFI_GUID gEdkiiNonDiscoverableXhciDeviceGuid;
+
+#endif
diff --git a/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
new file mode 100644
index 000000000000..976ae8387376
--- /dev/null
+++ b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
@@ -0,0 +1,77 @@
+/** @file
+ Protocol to describe devices that are not on a discoverable bus
+
+ Copyright (c) 2016, Linaro, Ltd. 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
+
+ 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 __NON_DISCOVERABLE_DEVICE_H__
+#define __NON_DISCOVERABLE_DEVICE_H__
+
+#include <IndustryStandard/Acpi.h>
+
+#define EDKII_NON_DISCOVERABLE_DEVICE_PROTOCOL_GUID \
+ { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 0x8d, 0x51, 0x4a } }
+
+//
+// Protocol interface structure
+//
+typedef struct _NON_DISCOVERABLE_DEVICE NON_DISCOVERABLE_DEVICE;
+
+//
+// Data Types
+//
+typedef enum {
+ NonDiscoverableDeviceDmaTypeCoherent,
+ NonDiscoverableDeviceDmaTypeNonCoherent,
+ NonDiscoverableDeviceDmaTypeMax,
+} NON_DISCOVERABLE_DEVICE_DMA_TYPE;
+
+//
+// Function Prototypes
+//
+
+/**
+ Perform device specific initialization before the device is started
+
+ @param This The non-discoverable device protocol pointer
+
+ @retval EFI_SUCCESS Initialization successful, the device may be used
+ @retval Other Initialization failed, device should not be started
+**/
+typedef
+EFI_STATUS
+(EFIAPI *NON_DISCOVERABLE_DEVICE_INIT) (
+ IN NON_DISCOVERABLE_DEVICE *This
+ );
+
+struct _NON_DISCOVERABLE_DEVICE {
+ //
+ // The type of device
+ //
+ CONST EFI_GUID *Type;
+ //
+ // Whether this device is DMA coherent
+ //
+ NON_DISCOVERABLE_DEVICE_DMA_TYPE DmaType;
+ //
+ // Initialization function for the device
+ //
+ NON_DISCOVERABLE_DEVICE_INIT Initialize;
+ //
+ // The MMIO and I/O regions owned by the device
+ //
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources;
+};
+
+extern EFI_GUID gEdkiiNonDiscoverableDeviceProtocolGuid;
+
+#endif
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 22898e3f7487..588f5e97dbc2 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -362,6 +362,17 @@ [Guids]
## Include/Guid/PiSmmMemoryAttributesTable.h
gEdkiiPiSmmMemoryAttributesTableGuid = { 0x6b9fd3f7, 0x16df, 0x45e8, {0xbd, 0x39, 0xb9, 0x4a, 0x66, 0x54, 0x1a, 0x5d}}
+ ## Include/Guid/NonDiscoverableDevice.h
+ gEdkiiNonDiscoverableAhciDeviceGuid = { 0xC7D35798, 0xE4D2, 0x4A93, {0xB1, 0x45, 0x54, 0x88, 0x9F, 0x02, 0x58, 0x4B } }
+ gEdkiiNonDiscoverableAmbaDeviceGuid = { 0x94440339, 0xCC93, 0x4506, {0xB4, 0xC6, 0xEE, 0x8D, 0x0F, 0x4C, 0xA1, 0x91 } }
+ gEdkiiNonDiscoverableEhciDeviceGuid = { 0xEAEE5615, 0x0CFD, 0x45FC, {0x87, 0x69, 0xA0, 0xD8, 0x56, 0x95, 0xAF, 0x85 } }
+ gEdkiiNonDiscoverableNvmeDeviceGuid = { 0xC5F25542, 0x2A79, 0x4A26, {0x81, 0xBB, 0x4E, 0xA6, 0x32, 0x33, 0xB3, 0x09 } }
+ gEdkiiNonDiscoverableOhciDeviceGuid = { 0xB20005B0, 0xBB2D, 0x496F, {0x86, 0x9C, 0x23, 0x0B, 0x44, 0x79, 0xE7, 0xD1 } }
+ gEdkiiNonDiscoverableSdhciDeviceGuid = { 0x1DD1D619, 0xF9B8, 0x463E, {0x86, 0x81, 0xD1, 0xDC, 0x7C, 0x07, 0xB7, 0x2C } }
+ gEdkiiNonDiscoverableUfsDeviceGuid = { 0x2EA77912, 0x80A8, 0x4947, {0xBE, 0x69, 0xCD, 0xD0, 0x0A, 0xFB, 0xE5, 0x56 } }
+ gEdkiiNonDiscoverableUhciDeviceGuid = { 0xA8CDA0A2, 0x4F37, 0x4A1B, {0x8E, 0x10, 0x8E, 0xF3, 0xCC, 0x3B, 0xF3, 0xA8 } }
+ gEdkiiNonDiscoverableXhciDeviceGuid = { 0xB1BE0BC5, 0x6C28, 0x442D, {0xAA, 0x37, 0x15, 0x1B, 0x42, 0x57, 0xBD, 0x78 } }
+
[Ppis]
## Include/Ppi/AtaController.h
gPeiAtaControllerPpiGuid = { 0xa45e60d1, 0xc719, 0x44aa, { 0xb0, 0x7a, 0xaa, 0x77, 0x7f, 0x85, 0x90, 0x6d }}
@@ -512,6 +523,9 @@ [Protocols]
# Include/Protocol/Ps2Policy.h
gEfiPs2PolicyProtocolGuid = { 0x4DF19259, 0xDC71, 0x4D46, { 0xBE, 0xF1, 0x35, 0x7B, 0xB5, 0x78, 0xC4, 0x18 } }
+ ## Include/Protocol/NonDiscoverableDevice.h
+ gEdkiiNonDiscoverableDeviceProtocolGuid = { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 0x8d, 0x51, 0x4a } }
+
#
# [Error.gEfiMdeModulePkgTokenSpaceGuid]
# 0x80000001 | Invalid value provided.
--
2.7.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v4 2/5] MdeModulePkg: introduce helper library to register non-discoverable devices
2016-11-25 15:42 [PATCH v4 0/5] MdeModulePkg: add support for non-discoverable devices Ard Biesheuvel
2016-11-25 15:42 ` [PATCH v4 1/5] MdeModulePkg: introduce non-discoverable device protocol Ard Biesheuvel
@ 2016-11-25 15:42 ` Ard Biesheuvel
2016-11-28 1:58 ` Ni, Ruiyu
2016-11-25 15:42 ` [PATCH v4 3/5] MdeModulePkg: implement generic PCI I/O driver for " Ard Biesheuvel
` (3 subsequent siblings)
5 siblings, 1 reply; 19+ messages in thread
From: Ard Biesheuvel @ 2016-11-25 15:42 UTC (permalink / raw)
To: edk2-devel, leif.lindholm, liming.gao, afish, ruiyu.ni,
michael.d.kinney, mw, feng.tian
Cc: Ard Biesheuvel
Non-discoverable devices need to be registered explicitly by the platform.
Introduce a helper library that takes care of this.
This implementation currently only supports registering devices that are
covered by one or more MMIO resources. The underlying protocol allows for
more flexibility than that, but this is currently sufficient for the use
cases that we know about.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h | 62 ++++++
MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c | 204 ++++++++++++++++++++
MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf | 46 +++++
MdeModulePkg/MdeModulePkg.dec | 4 +
MdeModulePkg/MdeModulePkg.dsc | 2 +
5 files changed, 318 insertions(+)
diff --git a/MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h b/MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h
new file mode 100644
index 000000000000..120d91466095
--- /dev/null
+++ b/MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h
@@ -0,0 +1,62 @@
+/** @file
+ Copyright (c) 2016, Linaro, Ltd. 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
+
+ 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 __NON_DISCOVERABLE_DEVICE_REGISTRATION_LIB_H__
+#define __NON_DISCOVERABLE_DEVICE_REGISTRATION_LIB_H__
+
+#include <Protocol/NonDiscoverableDevice.h>
+
+typedef enum {
+ NonDiscoverableDeviceTypeAhci,
+ NonDiscoverableDeviceTypeAmba,
+ NonDiscoverableDeviceTypeEhci,
+ NonDiscoverableDeviceTypeNvme,
+ NonDiscoverableDeviceTypeOhci,
+ NonDiscoverableDeviceTypeSdhci,
+ NonDiscoverableDeviceTypeUfs,
+ NonDiscoverableDeviceTypeUhci,
+ NonDiscoverableDeviceTypeXhci,
+ NonDiscoverableDeviceTypeMax,
+} NON_DISCOVERABLE_DEVICE_TYPE;
+
+/**
+ Register a non-discoverable MMIO device
+
+ @param[in] DeviceType The type of non-discoverable device
+ @param[in] DmaType Whether the device is DMA coherent
+ @param[in] InitFunc Initialization routine to be invoked when
+ the device is enabled
+ @param[in,out] Handle The handle onto which to install the
+ non-discoverable device protocol.
+ If Handle is NULL or *Handle is NULL, a
+ new handle will be allocated.
+ @param[in] NumMmioResources The number of UINTN base/size pairs that
+ follow, each describing an MMIO region
+ owned by the device
+
+ @retval EFI_SUCCESS The registration succeeded.
+ @retval Other The registration failed.
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterNonDiscoverableMmioDevice (
+ IN NON_DISCOVERABLE_DEVICE_TYPE Type,
+ IN NON_DISCOVERABLE_DEVICE_DMA_TYPE DmaType,
+ IN NON_DISCOVERABLE_DEVICE_INIT InitFunc,
+ IN OUT EFI_HANDLE *Handle OPTIONAL,
+ IN UINTN NumMmioResources,
+ ...
+ );
+
+#endif
diff --git a/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c b/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c
new file mode 100644
index 000000000000..94cd946b69d3
--- /dev/null
+++ b/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c
@@ -0,0 +1,204 @@
+/** @file
+ Copyright (c) 2016, Linaro, Ltd. 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
+
+ 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 <PiDxe.h>
+
+#include <Guid/NonDiscoverableDevice.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NonDiscoverableDeviceRegistrationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/DevicePath.h>
+#include <Protocol/NonDiscoverableDevice.h>
+
+STATIC
+CONST EFI_GUID *
+GetGuidFromType (
+ IN NON_DISCOVERABLE_DEVICE_TYPE Type
+ )
+{
+ switch (Type) {
+ case NonDiscoverableDeviceTypeAhci:
+ return &gEdkiiNonDiscoverableAhciDeviceGuid;
+
+ case NonDiscoverableDeviceTypeAmba:
+ return &gEdkiiNonDiscoverableAmbaDeviceGuid;
+
+ case NonDiscoverableDeviceTypeEhci:
+ return &gEdkiiNonDiscoverableEhciDeviceGuid;
+
+ case NonDiscoverableDeviceTypeNvme:
+ return &gEdkiiNonDiscoverableNvmeDeviceGuid;
+
+ case NonDiscoverableDeviceTypeOhci:
+ return &gEdkiiNonDiscoverableOhciDeviceGuid;
+
+ case NonDiscoverableDeviceTypeSdhci:
+ return &gEdkiiNonDiscoverableSdhciDeviceGuid;
+
+ case NonDiscoverableDeviceTypeUfs:
+ return &gEdkiiNonDiscoverableUfsDeviceGuid;
+
+ case NonDiscoverableDeviceTypeUhci:
+ return &gEdkiiNonDiscoverableUhciDeviceGuid;
+
+ case NonDiscoverableDeviceTypeXhci:
+ return &gEdkiiNonDiscoverableXhciDeviceGuid;
+
+ default:
+ return NULL;
+ }
+}
+
+#pragma pack (1)
+typedef struct {
+ VENDOR_DEVICE_PATH Vendor;
+ UINT64 BaseAddress;
+ UINT8 ResourceType;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} NON_DISCOVERABLE_DEVICE_PATH;
+#pragma pack ()
+
+/**
+ Register a non-discoverable MMIO device
+
+ @param[in] DeviceType The type of non-discoverable device
+ @param[in] DmaType Whether the device is DMA coherent
+ @param[in] InitFunc Initialization routine to be invoked when
+ the device is enabled
+ @param[in,out] Handle The handle onto which to install the
+ non-discoverable device protocol.
+ If Handle is NULL or *Handle is NULL, a
+ new handle will be allocated.
+ @param[in] NumMmioResources The number of UINTN base/size pairs that
+ follow, each describing an MMIO region
+ owned by the device
+
+ @retval EFI_SUCCESS The registration succeeded.
+ @retval EFI_INVALID_PARAMETER An invalid argument was given
+ @retval Other The registration failed.
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterNonDiscoverableMmioDevice (
+ IN NON_DISCOVERABLE_DEVICE_TYPE Type,
+ IN NON_DISCOVERABLE_DEVICE_DMA_TYPE DmaType,
+ IN NON_DISCOVERABLE_DEVICE_INIT InitFunc,
+ IN OUT EFI_HANDLE *Handle OPTIONAL,
+ IN UINTN NumMmioResources,
+ ...
+ )
+{
+ NON_DISCOVERABLE_DEVICE *Device;
+ NON_DISCOVERABLE_DEVICE_PATH *DevicePath;
+ EFI_HANDLE LocalHandle;
+ EFI_STATUS Status;
+ UINTN AllocSize;
+ UINTN Index;
+ VA_LIST Args;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
+ EFI_ACPI_END_TAG_DESCRIPTOR *End;
+ UINTN Base, Size;
+
+ if (Type >= NonDiscoverableDeviceTypeMax ||
+ DmaType >= NonDiscoverableDeviceDmaTypeMax ||
+ NumMmioResources == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Handle == NULL) {
+ Handle = &LocalHandle;
+ LocalHandle = NULL;
+ }
+
+ AllocSize = sizeof *Device +
+ NumMmioResources * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR);
+ Device = (NON_DISCOVERABLE_DEVICE *)AllocateZeroPool (AllocSize);
+ if (Device == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Device->Type = GetGuidFromType (Type);
+ ASSERT (Device->Type != NULL);
+
+ Device->DmaType = DmaType;
+ Device->Initialize = InitFunc;
+ Device->Resources = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(Device + 1);
+
+ VA_START (Args, NumMmioResources);
+ for (Index = 0; Index < NumMmioResources; Index++) {
+ Desc = &Device->Resources [Index];
+ Base = VA_ARG (Args, UINTN);
+ Size = VA_ARG (Args, UINTN);
+
+ Desc->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Desc->Len = sizeof *Desc - 3;
+ Desc->AddrRangeMin = Base;
+ Desc->AddrLen = Size;
+ Desc->AddrRangeMax = Base + Size - 1;
+ Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Desc->AddrSpaceGranularity = (Base + Size > SIZE_4GB) ? 64 : 32;
+ Desc->AddrTranslationOffset = 0;
+ }
+ VA_END (Args);
+
+ End = (EFI_ACPI_END_TAG_DESCRIPTOR *)&Device->Resources [NumMmioResources];
+
+ End->Desc = ACPI_END_TAG_DESCRIPTOR;
+ End->Checksum = 0;
+
+ DevicePath = (NON_DISCOVERABLE_DEVICE_PATH *)CreateDeviceNode (
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ sizeof (*DevicePath));
+ if (DevicePath == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeDevice;
+ }
+
+ CopyGuid (&DevicePath->Vendor.Guid, &gEdkiiNonDiscoverableDeviceProtocolGuid);
+
+ //
+ // Use the base address and type of the first region to
+ // make the device path unique
+ //
+ DevicePath->BaseAddress = Device->Resources [0].AddrRangeMin;
+ DevicePath->ResourceType = Device->Resources [0].ResType;
+
+ SetDevicePathNodeLength (&DevicePath->Vendor,
+ sizeof (*DevicePath) - sizeof (DevicePath->End));
+ SetDevicePathEndNode (&DevicePath->End);
+
+ Status = gBS->InstallMultipleProtocolInterfaces (Handle,
+ &gEdkiiNonDiscoverableDeviceProtocolGuid, Device,
+ &gEfiDevicePathProtocolGuid, DevicePath,
+ NULL);
+ if (EFI_ERROR (Status)) {
+ goto FreeDevicePath;
+ }
+ return EFI_SUCCESS;
+
+FreeDevicePath:
+ FreePool (DevicePath);
+
+FreeDevice:
+ FreePool (Device);
+
+ return Status;
+}
diff --git a/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf b/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
new file mode 100644
index 000000000000..ba32324c303e
--- /dev/null
+++ b/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
@@ -0,0 +1,46 @@
+# @file
+# Copyright (c) 2016, Linaro, Ltd. 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
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+[Defines]
+ INF_VERSION = 0x00010019
+ BASE_NAME = NonDiscoverableDeviceRegistrationLib
+ FILE_GUID = 8802ae41-8184-49cb-8aec-62627cd7ceb4
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NonDiscoverableDeviceRegistrationLib
+
+[Sources]
+ NonDiscoverableDeviceRegistrationLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ UefiBootServicesTableLib
+
+[Protocols]
+ gEdkiiNonDiscoverableDeviceProtocolGuid
+
+[Guids]
+ gEdkiiNonDiscoverableAhciDeviceGuid
+ gEdkiiNonDiscoverableAmbaDeviceGuid
+ gEdkiiNonDiscoverableEhciDeviceGuid
+ gEdkiiNonDiscoverableNvmeDeviceGuid
+ gEdkiiNonDiscoverableOhciDeviceGuid
+ gEdkiiNonDiscoverableSdhciDeviceGuid
+ gEdkiiNonDiscoverableUfsDeviceGuid
+ gEdkiiNonDiscoverableUhciDeviceGuid
+ gEdkiiNonDiscoverableXhciDeviceGuid
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 588f5e97dbc2..315337fa4000 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -161,6 +161,10 @@ [LibraryClasses]
#
FmpAuthenticationLib|Include/Library/FmpAuthenticationLib.h
+ ## @libraryclass Provides a service to register non-discoverable device
+ ##
+ NonDiscoverableDeviceRegistrationLib|Include/Library/NonDiscoverableDeviceRegistrationLib.h
+
[Guids]
## MdeModule package token space guid
# Include/Guid/MdeModulePkgTokenSpace.h
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index bfecb3078737..20e5e8c78be0 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -102,6 +102,7 @@ [LibraryClasses]
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
+ NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenticationLibNull/FmpAuthenticationLibNull.inf
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
@@ -322,6 +323,7 @@ [Components]
MdeModulePkg/Library/PeiIpmiLibIpmiPpi/PeiIpmiLibIpmiPpi.inf
MdeModulePkg/Library/SmmIpmiLibSmmIpmiProtocol/SmmIpmiLibSmmIpmiProtocol.inf
MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
+ MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf
--
2.7.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v4 3/5] MdeModulePkg: implement generic PCI I/O driver for non-discoverable devices
2016-11-25 15:42 [PATCH v4 0/5] MdeModulePkg: add support for non-discoverable devices Ard Biesheuvel
2016-11-25 15:42 ` [PATCH v4 1/5] MdeModulePkg: introduce non-discoverable device protocol Ard Biesheuvel
2016-11-25 15:42 ` [PATCH v4 2/5] MdeModulePkg: introduce helper library to register non-discoverable devices Ard Biesheuvel
@ 2016-11-25 15:42 ` Ard Biesheuvel
2016-11-28 1:56 ` Ni, Ruiyu
2016-11-25 15:42 ` [PATCH v4 4/5] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Ard Biesheuvel
` (2 subsequent siblings)
5 siblings, 1 reply; 19+ messages in thread
From: Ard Biesheuvel @ 2016-11-25 15:42 UTC (permalink / raw)
To: edk2-devel, leif.lindholm, liming.gao, afish, ruiyu.ni,
michael.d.kinney, mw, feng.tian
Cc: Ard Biesheuvel
This implements support for non-discoverable PCI compatible devices, i.e,
devices that are not on a PCI bus but that can be controlled by generic PCI
drivers in EDK2.
This is implemented as a UEFI driver, which means we take full advantage
of the UEFI driver model, and only instantiate those devices that are
necessary for booting.
Care is taken to deal with DMA addressing limitations: DMA mappings and
allocations are moved below 4 GB if the PCI driver has not informed us
that the device being driven is 64-bit DMA capable. DMA is implemented as
coherent, support for non-coherent DMA is implemented by a subsequent patch.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c | 75 ++
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c | 235 ++++++
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf | 52 ++
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c | 797 ++++++++++++++++++++
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h | 84 +++
MdeModulePkg/MdeModulePkg.dsc | 1 +
6 files changed, 1244 insertions(+)
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c
new file mode 100644
index 000000000000..6e51d00fe434
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c
@@ -0,0 +1,75 @@
+/** @file
+
+ Copyright (C) 2016, Linaro Ltd. 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
+
+ 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 "NonDiscoverablePciDeviceIo.h"
+
+//
+// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
+// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
+// in English, for display on standard console devices. This is recommended for
+// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
+// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
+//
+
+STATIC
+EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
+ { "eng;en", L"PCI I/O protocol emulation driver for non-discoverable devices" },
+ { NULL, NULL }
+};
+
+EFI_COMPONENT_NAME_PROTOCOL gComponentName;
+
+STATIC
+EFI_STATUS
+EFIAPI
+NonDiscoverablePciGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gComponentName) // Iso639Language
+ );
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+NonDiscoverablePciGetDeviceName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE DeviceHandle,
+ IN EFI_HANDLE ChildHandle,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
+ &NonDiscoverablePciGetDriverName,
+ &NonDiscoverablePciGetDeviceName,
+ "eng" // SupportedLanguages, ISO 639-2 language codes
+};
+
+EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &NonDiscoverablePciGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &NonDiscoverablePciGetDeviceName,
+ "en" // SupportedLanguages, RFC 4646 language codes
+};
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
new file mode 100644
index 000000000000..ee765d7a5d9c
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
@@ -0,0 +1,235 @@
+/** @file
+
+ Copyright (C) 2016, Linaro Ltd. 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
+
+ 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 "NonDiscoverablePciDeviceIo.h"
+
+#include <Protocol/DriverBinding.h>
+
+//
+// We only support the following device types
+//
+STATIC
+CONST EFI_GUID * CONST
+SupportedNonDiscoverableDevices [] = {
+ &gEdkiiNonDiscoverableAhciDeviceGuid,
+ &gEdkiiNonDiscoverableEhciDeviceGuid,
+ &gEdkiiNonDiscoverableNvmeDeviceGuid,
+ &gEdkiiNonDiscoverableOhciDeviceGuid,
+ &gEdkiiNonDiscoverableSdhciDeviceGuid,
+ &gEdkiiNonDiscoverableUfsDeviceGuid,
+ &gEdkiiNonDiscoverableUhciDeviceGuid,
+ &gEdkiiNonDiscoverableXhciDeviceGuid,
+};
+
+//
+// Probe, start and stop functions of this driver, called by the DXE core for
+// specific devices.
+//
+// The following specifications document these interfaces:
+// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
+// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
+//
+// The implementation follows:
+// - Driver Writer's Guide for UEFI 2.3.1 v1.01
+// - 5.1.3.4 OpenProtocol() and CloseProtocol()
+// - UEFI Spec 2.3.1 + Errata C
+// - 6.3 Protocol Handler Services
+//
+
+STATIC
+EFI_STATUS
+EFIAPI
+NonDiscoverablePciDeviceSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE DeviceHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ NON_DISCOVERABLE_DEVICE *Device;
+ EFI_STATUS Status;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
+ INTN Idx;
+
+ Status = gBS->OpenProtocol (DeviceHandle,
+ &gEdkiiNonDiscoverableDeviceProtocolGuid, (VOID **)&Device,
+ This->DriverBindingHandle, DeviceHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Restricted to DMA coherent for now
+ //
+ Status = EFI_UNSUPPORTED;
+ if (Device->DmaType != NonDiscoverableDeviceDmaTypeCoherent) {
+ goto CloseProtocol;
+ }
+
+ for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++) {
+ if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices [Idx])) {
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto CloseProtocol;
+ }
+
+ //
+ // We only support MMIO devices, so iterate over the resources to ensure
+ // that they only describe things that we can handle
+ //
+ for (Desc = Device->Resources; Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
+ Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {
+ if (Desc->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR ||
+ Desc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+ }
+
+CloseProtocol:
+ gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
+ This->DriverBindingHandle, DeviceHandle);
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+NonDiscoverablePciDeviceStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE DeviceHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+ EFI_STATUS Status;
+
+ Dev = AllocateZeroPool (sizeof *Dev);
+ if (Dev == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = gBS->OpenProtocol (DeviceHandle,
+ &gEdkiiNonDiscoverableDeviceProtocolGuid,
+ (VOID **)&Dev->Device, This->DriverBindingHandle,
+ DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
+ if (EFI_ERROR (Status)) {
+ goto FreeDev;
+ }
+
+ InitializePciIoProtocol (Dev);
+
+ //
+ // Setup complete, attempt to export the driver instance's
+ // EFI_PCI_IO_PROTOCOL interface.
+ //
+ Dev->Signature = NON_DISCOVERABLE_PCI_DEVICE_SIG;
+ Status = gBS->InstallProtocolInterface (&DeviceHandle, &gEfiPciIoProtocolGuid,
+ EFI_NATIVE_INTERFACE, &Dev->PciIo);
+ if (EFI_ERROR (Status)) {
+ goto CloseProtocol;
+ }
+
+ return EFI_SUCCESS;
+
+CloseProtocol:
+ gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
+ This->DriverBindingHandle, DeviceHandle);
+
+FreeDev:
+ FreePool (Dev);
+
+ return Status;
+}
+
+
+STATIC
+EFI_STATUS
+EFIAPI
+NonDiscoverablePciDeviceStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE DeviceHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+
+ Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+ (VOID **)&PciIo, This->DriverBindingHandle, DeviceHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (PciIo);
+
+ //
+ // Handle Stop() requests for in-use driver instances gracefully.
+ //
+ Status = gBS->UninstallProtocolInterface (DeviceHandle,
+ &gEfiPciIoProtocolGuid, &Dev->PciIo);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
+ This->DriverBindingHandle, DeviceHandle);
+
+ FreePool (Dev);
+
+ return EFI_SUCCESS;
+}
+
+
+//
+// The static object that groups the Supported() (ie. probe), Start() and
+// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
+// C, 10.1 EFI Driver Binding Protocol.
+//
+STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
+ &NonDiscoverablePciDeviceSupported,
+ &NonDiscoverablePciDeviceStart,
+ &NonDiscoverablePciDeviceStop,
+ 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
+ NULL,
+ NULL
+};
+
+//
+// Entry point of this driver.
+//
+EFI_STATUS
+EFIAPI
+NonDiscoverablePciDeviceDxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gDriverBinding,
+ ImageHandle,
+ &gComponentName,
+ &gComponentName2
+ );
+}
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
new file mode 100644
index 000000000000..996fe310e0e3
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
@@ -0,0 +1,52 @@
+## @file
+# Copyright (C) 2016, Linaro Ltd.
+#
+# 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010019
+ BASE_NAME = NonDiscoverablePciDeviceDxe
+ FILE_GUID = 71fd84cd-353b-464d-b7a4-6ea7b96995cb
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = NonDiscoverablePciDeviceDxeEntryPoint
+
+[Sources]
+ ComponentName.c
+ NonDiscoverablePciDeviceDxe.c
+ NonDiscoverablePciDeviceIo.c
+ NonDiscoverablePciDeviceIo.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Protocols]
+ gEfiPciIoProtocolGuid ## BY_START
+ gEdkiiNonDiscoverableDeviceProtocolGuid ## TO_START
+
+[Guids]
+ gEdkiiNonDiscoverableAhciDeviceGuid
+ gEdkiiNonDiscoverableEhciDeviceGuid
+ gEdkiiNonDiscoverableNvmeDeviceGuid
+ gEdkiiNonDiscoverableOhciDeviceGuid
+ gEdkiiNonDiscoverableSdhciDeviceGuid
+ gEdkiiNonDiscoverableUfsDeviceGuid
+ gEdkiiNonDiscoverableUhciDeviceGuid
+ gEdkiiNonDiscoverableXhciDeviceGuid
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
new file mode 100644
index 000000000000..fd59267a8d66
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
@@ -0,0 +1,797 @@
+/** @file
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2016, Linaro, Ltd. 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
+
+ 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 "NonDiscoverablePciDeviceIo.h"
+
+#include <IndustryStandard/Acpi.h>
+
+#include <Protocol/PciRootBridgeIo.h>
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS AllocAddress;
+ VOID *HostAddress;
+ EFI_PCI_IO_PROTOCOL_OPERATION Operation;
+ UINTN NumberOfBytes;
+} NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO;
+
+//
+// Get the resource associated with BAR number 'BarIndex'.
+//
+STATIC
+EFI_STATUS
+GetBarResource (
+ IN NON_DISCOVERABLE_PCI_DEVICE *Dev,
+ IN UINT8 BarIndex,
+ OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptor
+ )
+{
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
+
+ if (BarIndex < Dev->BarOffset) {
+ return EFI_NOT_FOUND;
+ }
+
+ BarIndex -= Dev->BarOffset;
+
+ for (Desc = Dev->Device->Resources;
+ Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
+ Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {
+
+ if (BarIndex == 0) {
+ *Descriptor = Desc;
+ return EFI_SUCCESS;
+ }
+
+ BarIndex -= 1;
+ }
+ return EFI_NOT_FOUND;
+}
+
+STATIC
+EFI_STATUS
+PciIoPollMem (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+PciIoPollIo (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+PciIoMemRW (
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN UINTN DstStride,
+ IN VOID *Dst,
+ IN UINTN SrcStride,
+ OUT CONST VOID *Src
+ )
+{
+ volatile UINT8 *Dst8;
+ volatile UINT16 *Dst16;
+ volatile UINT32 *Dst32;
+ volatile CONST UINT8 *Src8;
+ volatile CONST UINT16 *Src16;
+ volatile CONST UINT32 *Src32;
+
+ //
+ // Loop for each iteration and move the data
+ //
+ switch (Width & 0x3) {
+ case EfiPciWidthUint8:
+ Dst8 = (UINT8 *)Dst;
+ Src8 = (UINT8 *)Src;
+ for (;Count > 0; Count--, Dst8 += DstStride, Src8 += SrcStride) {
+ *Dst8 = *Src8;
+ }
+ break;
+ case EfiPciWidthUint16:
+ Dst16 = (UINT16 *)Dst;
+ Src16 = (UINT16 *)Src;
+ for (;Count > 0; Count--, Dst16 += DstStride, Src16 += SrcStride) {
+ *Dst16 = *Src16;
+ }
+ break;
+ case EfiPciWidthUint32:
+ Dst32 = (UINT32 *)Dst;
+ Src32 = (UINT32 *)Src;
+ for (;Count > 0; Count--, Dst32 += DstStride, Src32 += SrcStride) {
+ *Dst32 = *Src32;
+ }
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+PciIoMemRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+ UINTN AlignMask;
+ VOID *Address;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
+ EFI_STATUS Status;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
+
+ //
+ // Only allow accesses to the BARs we emulate
+ //
+ Status = GetBarResource (Dev, BarIndex, &Desc);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Offset + (Count << (Width & 0x3)) > Desc->AddrLen) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Address = (VOID *)(UINTN)(Desc->AddrRangeMin + Offset);
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if ((UINTN)Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ case EfiPciWidthUint16:
+ case EfiPciWidthUint32:
+ case EfiPciWidthUint64:
+ return PciIoMemRW (Width, Count, 1, Buffer, 1, Address);
+
+ case EfiPciWidthFifoUint8:
+ case EfiPciWidthFifoUint16:
+ case EfiPciWidthFifoUint32:
+ case EfiPciWidthFifoUint64:
+ return PciIoMemRW (Width, Count, 1, Buffer, 0, Address);
+
+ case EfiPciWidthFillUint8:
+ case EfiPciWidthFillUint16:
+ case EfiPciWidthFillUint32:
+ case EfiPciWidthFillUint64:
+ return PciIoMemRW (Width, Count, 0, Buffer, 1, Address);
+
+ default:
+ break;
+ }
+ return EFI_INVALID_PARAMETER;
+}
+
+STATIC
+EFI_STATUS
+PciIoMemWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+ UINTN AlignMask;
+ VOID *Address;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
+ EFI_STATUS Status;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
+
+ //
+ // Only allow accesses to the BARs we emulate
+ //
+ Status = GetBarResource (Dev, BarIndex, &Desc);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Offset + (Count << (Width & 0x3)) > Desc->AddrLen) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Address = (VOID *)(UINTN)(Desc->AddrRangeMin + Offset);
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if ((UINTN)Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ case EfiPciWidthUint16:
+ case EfiPciWidthUint32:
+ case EfiPciWidthUint64:
+ return PciIoMemRW (Width, Count, 1, Address, 1, Buffer);
+
+ case EfiPciWidthFifoUint8:
+ case EfiPciWidthFifoUint16:
+ case EfiPciWidthFifoUint32:
+ case EfiPciWidthFifoUint64:
+ return PciIoMemRW (Width, Count, 0, Address, 1, Buffer);
+
+ case EfiPciWidthFillUint8:
+ case EfiPciWidthFillUint16:
+ case EfiPciWidthFillUint32:
+ case EfiPciWidthFillUint64:
+ return PciIoMemRW (Width, Count, 1, Address, 0, Buffer);
+
+ default:
+ break;
+ }
+ return EFI_INVALID_PARAMETER;
+}
+
+STATIC
+EFI_STATUS
+PciIoIoRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+PciIoIoWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+PciIoPciRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+ VOID *Address;
+ UINTN Length;
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum || Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
+ Address = (UINT8 *)&Dev->ConfigSpace + Offset;
+ Length = Count << ((UINTN)Width & 0x3);
+
+ if (Offset + Length > sizeof (Dev->ConfigSpace)) {
+ //
+ // Read all zeroes for config space accesses beyond the first
+ // 64 bytes
+ //
+ Length -= sizeof (Dev->ConfigSpace) - Offset;
+ ZeroMem ((UINT8 *)Buffer + sizeof (Dev->ConfigSpace) - Offset, Length);
+
+ Count -= Length >> ((UINTN)Width & 0x3);
+ }
+ return PciIoMemRW (Width, Count, 1, Buffer, 1, Address);
+}
+
+STATIC
+EFI_STATUS
+PciIoPciWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+ VOID *Address;
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum || Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
+ Address = (UINT8 *)&Dev->ConfigSpace + Offset;
+
+ if (Offset + (Count << ((UINTN)Width & 0x3)) > sizeof (Dev->ConfigSpace)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return PciIoMemRW (Width, Count, 1, Address, 1, Buffer);
+}
+
+STATIC
+EFI_STATUS
+PciIoCopyMem (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 DestBarIndex,
+ IN UINT64 DestOffset,
+ IN UINT8 SrcBarIndex,
+ IN UINT64 SrcOffset,
+ IN UINTN Count
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+CoherentPciIoMap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+ EFI_STATUS Status;
+ NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;
+
+ //
+ // If HostAddress exceeds 4 GB, and this device does not support 64-bit DMA
+ // addressing, we need to allocate a bounce buffer and copy over the data.
+ //
+ Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
+ if ((Dev->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0 &&
+ (UINTN)HostAddress + *NumberOfBytes > SIZE_4GB) {
+
+ //
+ // Bounce buffering is not possible for consistent mappings
+ //
+ if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
+ return EFI_UNSUPPORTED;
+ }
+
+ MapInfo = AllocatePool (sizeof *MapInfo);
+ if (MapInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ MapInfo->AllocAddress = MAX_UINT32;
+ MapInfo->HostAddress = HostAddress;
+ MapInfo->Operation = Operation;
+ MapInfo->NumberOfBytes = *NumberOfBytes;
+
+ Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData,
+ EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),
+ &MapInfo->AllocAddress);
+ if (EFI_ERROR (Status)) {
+ //
+ // If we fail here, it is likely because the system has no memory below
+ // 4 GB to begin with. There is not much we can do about that other than
+ // fail the map request.
+ //
+ FreePool (MapInfo);
+ return EFI_DEVICE_ERROR;
+ }
+ if (Operation == EfiPciIoOperationBusMasterRead) {
+ gBS->CopyMem ((VOID *)(UINTN)MapInfo->AllocAddress, HostAddress,
+ *NumberOfBytes);
+ }
+ *DeviceAddress = MapInfo->AllocAddress;
+ *Mapping = MapInfo;
+ } else {
+ *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
+ *Mapping = NULL;
+ }
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+CoherentPciIoUnmap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;
+
+ MapInfo = Mapping;
+ if (MapInfo != NULL) {
+ if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {
+ gBS->CopyMem (MapInfo->HostAddress, (VOID *)(UINTN)MapInfo->AllocAddress,
+ MapInfo->NumberOfBytes);
+ }
+ gBS->FreePages (MapInfo->AllocAddress,
+ EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes));
+ FreePool (MapInfo);
+ }
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+CoherentPciIoAllocateBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+ EFI_PHYSICAL_ADDRESS AllocAddress;
+ EFI_ALLOCATE_TYPE AllocType;
+ EFI_STATUS Status;
+
+ if ((Attributes & ~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE |
+ EFI_PCI_ATTRIBUTE_MEMORY_CACHED)) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Allocate below 4 GB if the dual address cycle attribute has not
+ // been set. If the system has no memory available below 4 GB, there
+ // is little we can do except propagate the error.
+ //
+ Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
+ if ((Dev->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {
+ AllocAddress = MAX_UINT32;
+ AllocType = AllocateMaxAddress;
+ } else {
+ AllocType = AllocateAnyPages;
+ }
+
+ Status = gBS->AllocatePages (AllocType, MemoryType, Pages, &AllocAddress);
+ if (!EFI_ERROR (Status)) {
+ *HostAddress = (VOID *)(UINTN)AllocAddress;
+ }
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+CoherentPciIoFreeBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ )
+{
+ FreePages (HostAddress, Pages);
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+EFI_STATUS
+PciIoFlush (
+ IN EFI_PCI_IO_PROTOCOL *This
+ )
+{
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+PciIoGetLocation (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ OUT UINTN *SegmentNumber,
+ OUT UINTN *BusNumber,
+ OUT UINTN *DeviceNumber,
+ OUT UINTN *FunctionNumber
+ )
+{
+ if (SegmentNumber == NULL ||
+ BusNumber == NULL ||
+ DeviceNumber == NULL ||
+ FunctionNumber == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *SegmentNumber = 0;
+ *BusNumber = 0xff;
+ *DeviceNumber = 0;
+ *FunctionNumber = 0;
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+PciIoAttributes (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
+ IN UINT64 Attributes,
+ OUT UINT64 *Result OPTIONAL
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+ BOOLEAN Enable;
+
+ Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
+
+ Enable = FALSE;
+ switch (Operation) {
+ case EfiPciIoAttributeOperationGet:
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ *Result = Dev->Attributes;
+ break;
+
+ case EfiPciIoAttributeOperationSupported:
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ *Result = EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
+ break;
+
+ case EfiPciIoAttributeOperationEnable:
+ Attributes |= Dev->Attributes;
+ case EfiPciIoAttributeOperationSet:
+ Enable = ((~Dev->Attributes & Attributes) & EFI_PCI_DEVICE_ENABLE) != 0;
+ Dev->Attributes = Attributes;
+ break;
+
+ case EfiPciIoAttributeOperationDisable:
+ Dev->Attributes &= ~Attributes;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ };
+
+ //
+ // If we're setting any of the EFI_PCI_DEVICE_ENABLE bits, perform
+ // the device specific initialization now.
+ //
+ if (Enable && !Dev->Enabled && Dev->Device->Initialize != NULL) {
+ Dev->Device->Initialize (Dev->Device);
+ Dev->Enabled = TRUE;
+ }
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+PciIoGetBarAttributes (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT8 BarIndex,
+ OUT UINT64 *Supports OPTIONAL,
+ OUT VOID **Resources OPTIONAL
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor, *BarDesc;
+ EFI_ACPI_END_TAG_DESCRIPTOR *End;
+ EFI_STATUS Status;
+
+ if (Supports == NULL && Resources == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
+
+ Status = GetBarResource (Dev, BarIndex, &BarDesc);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Don't expose any configurable attributes for our emulated BAR
+ //
+ if (Supports != NULL) {
+ *Supports = 0;
+ }
+
+ if (Resources != NULL) {
+ Descriptor = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+ if (Descriptor == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (Descriptor, BarDesc, sizeof *Descriptor);
+
+ End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);
+ End->Desc = ACPI_END_TAG_DESCRIPTOR;
+ End->Checksum = 0;
+
+ *Resources = Descriptor;
+ }
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+PciIoSetBarAttributes (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN UINT8 BarIndex,
+ IN OUT UINT64 *Offset,
+ IN OUT UINT64 *Length
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+STATIC CONST EFI_PCI_IO_PROTOCOL PciIoTemplate =
+{
+ PciIoPollMem,
+ PciIoPollIo,
+ { PciIoMemRead, PciIoMemWrite },
+ { PciIoIoRead, PciIoIoWrite },
+ { PciIoPciRead, PciIoPciWrite },
+ PciIoCopyMem,
+ CoherentPciIoMap,
+ CoherentPciIoUnmap,
+ CoherentPciIoAllocateBuffer,
+ CoherentPciIoFreeBuffer,
+ PciIoFlush,
+ PciIoGetLocation,
+ PciIoAttributes,
+ PciIoGetBarAttributes,
+ PciIoSetBarAttributes,
+ 0,
+ 0
+};
+
+VOID
+InitializePciIoProtocol (
+ NON_DISCOVERABLE_PCI_DEVICE *Dev
+ )
+{
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
+ INTN Idx;
+
+ InitializeListHead (&Dev->UncachedAllocationList);
+
+ Dev->ConfigSpace.Hdr.VendorId = PCI_ID_VENDOR_UNKNOWN;
+ Dev->ConfigSpace.Hdr.DeviceId = PCI_ID_DEVICE_DONTCARE;
+
+ // Copy protocol structure
+ CopyMem(&Dev->PciIo, &PciIoTemplate, sizeof PciIoTemplate);
+
+ if (CompareGuid (Dev->Device->Type, &gEdkiiNonDiscoverableAhciDeviceGuid)) {
+ Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_MASS_STORAGE_AHCI;
+ Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_MASS_STORAGE_SATADPA;
+ Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_MASS_STORAGE;
+ Dev->BarOffset = 5;
+ } else if (CompareGuid (Dev->Device->Type,
+ &gEdkiiNonDiscoverableEhciDeviceGuid)) {
+ Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_EHCI;
+ Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;
+ Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;
+ Dev->BarOffset = 0;
+ } else if (CompareGuid (Dev->Device->Type,
+ &gEdkiiNonDiscoverableNvmeDeviceGuid)) {
+ Dev->ConfigSpace.Hdr.ClassCode[0] = 0x2; // PCI_IF_NVMHCI
+ Dev->ConfigSpace.Hdr.ClassCode[1] = 0x8; // PCI_CLASS_MASS_STORAGE_NVM
+ Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_MASS_STORAGE;
+ Dev->BarOffset = 0;
+ } else if (CompareGuid (Dev->Device->Type,
+ &gEdkiiNonDiscoverableOhciDeviceGuid)) {
+ Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_OHCI;
+ Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;
+ Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;
+ Dev->BarOffset = 0;
+ } else if (CompareGuid (Dev->Device->Type,
+ &gEdkiiNonDiscoverableSdhciDeviceGuid)) {
+ Dev->ConfigSpace.Hdr.ClassCode[0] = 0x0; // don't care
+ Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_SUBCLASS_SD_HOST_CONTROLLER;
+ Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SYSTEM_PERIPHERAL;
+ Dev->BarOffset = 0;
+ } else if (CompareGuid (Dev->Device->Type,
+ &gEdkiiNonDiscoverableXhciDeviceGuid)) {
+ Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_XHCI;
+ Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;
+ Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;
+ Dev->BarOffset = 0;
+ } else if (CompareGuid (Dev->Device->Type,
+ &gEdkiiNonDiscoverableUhciDeviceGuid)) {
+ Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_UHCI;
+ Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;
+ Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;
+ Dev->BarOffset = 0;
+ } else if (CompareGuid (Dev->Device->Type,
+ &gEdkiiNonDiscoverableUfsDeviceGuid)) {
+ Dev->ConfigSpace.Hdr.ClassCode[0] = 0x0; // don't care
+ Dev->ConfigSpace.Hdr.ClassCode[1] = 0x9; // UFS controller subclass;
+ Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_MASS_STORAGE;
+ Dev->BarOffset = 0;
+ } else {
+ ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // Iterate over the resources to populate the virtual BARs
+ //
+ Idx = Dev->BarOffset;
+ for (Desc = Dev->Device->Resources, Dev->BarCount = 0;
+ Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
+ Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {
+
+ ASSERT (Desc->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ ASSERT (Desc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM);
+
+ if (Idx >= PCI_MAX_BARS ||
+ (Idx == PCI_MAX_BARS - 1 && Desc->AddrSpaceGranularity == 64)) {
+ DEBUG ((DEBUG_ERROR,
+ "%a: resource count exceeds number of emulated BARs\n",
+ __FUNCTION__));
+ ASSERT (FALSE);
+ break;
+ }
+
+ Dev->ConfigSpace.Device.Bar[Idx] = (UINT32)Desc->AddrRangeMin;
+ Dev->BarCount++;
+
+ if (Desc->AddrSpaceGranularity == 64) {
+ Dev->ConfigSpace.Device.Bar[Idx] |= 0x4;
+ Dev->ConfigSpace.Device.Bar[++Idx] = (UINT32)(Desc->AddrRangeMin >> 32);
+ }
+ }
+}
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
new file mode 100644
index 000000000000..bc0a3d3258f9
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
@@ -0,0 +1,84 @@
+/** @file
+
+ Copyright (C) 2016, Linaro Ltd. 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
+
+ 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 __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
+#define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include <Protocol/ComponentName.h>
+#include <Protocol/NonDiscoverableDevice.h>
+#include <Protocol/PciIo.h>
+
+#define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I', 'D')
+
+#define NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(PciIoPointer) \
+ CR (PciIoPointer, NON_DISCOVERABLE_PCI_DEVICE, PciIo, \
+ NON_DISCOVERABLE_PCI_DEVICE_SIG)
+
+#define PCI_ID_VENDOR_UNKNOWN 0xffff
+#define PCI_ID_DEVICE_DONTCARE 0x0000
+
+#define PCI_MAX_BARS 6
+
+typedef struct {
+ UINT32 Signature;
+ //
+ // The bound non-discoverable device protocol instance
+ //
+ NON_DISCOVERABLE_DEVICE *Device;
+ //
+ // The exposed PCI I/O protocol instance.
+ //
+ EFI_PCI_IO_PROTOCOL PciIo;
+ //
+ // The emulated PCI config space of the device. Only the minimally required
+ // items are assigned.
+ //
+ PCI_TYPE00 ConfigSpace;
+ //
+ // The first virtual BAR to assign based on the resources described
+ // by the non-discoverable device.
+ //
+ UINT32 BarOffset;
+ //
+ // The number of virtual BARs we expose based on the number of
+ // resources
+ //
+ UINT32 BarCount;
+ //
+ // The PCI I/O attributes for this device
+ //
+ UINT64 Attributes;
+ //
+ // Whether this device has been enabled
+ //
+ BOOLEAN Enabled;
+} NON_DISCOVERABLE_PCI_DEVICE;
+
+VOID
+InitializePciIoProtocol (
+ NON_DISCOVERABLE_PCI_DEVICE *Device
+ );
+
+extern EFI_COMPONENT_NAME_PROTOCOL gComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gComponentName2;
+
+#endif
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 20e5e8c78be0..5dd30556cb3c 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -265,6 +265,7 @@ [Components]
MdeModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf
MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
+ MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
MdeModulePkg/Core/Dxe/DxeMain.inf {
<LibraryClasses>
--
2.7.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v4 4/5] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA
2016-11-25 15:42 [PATCH v4 0/5] MdeModulePkg: add support for non-discoverable devices Ard Biesheuvel
` (2 preceding siblings ...)
2016-11-25 15:42 ` [PATCH v4 3/5] MdeModulePkg: implement generic PCI I/O driver for " Ard Biesheuvel
@ 2016-11-25 15:42 ` Ard Biesheuvel
2016-11-28 2:25 ` Ni, Ruiyu
2016-11-25 15:42 ` [PATCH v4 5/5] Omap35xxPkg/PciEmulation: port to new non-discoverable device infrastructure Ard Biesheuvel
2016-11-27 10:18 ` [PATCH v4 0/5] MdeModulePkg: add support for non-discoverable devices Marcin Wojtas
5 siblings, 1 reply; 19+ messages in thread
From: Ard Biesheuvel @ 2016-11-25 15:42 UTC (permalink / raw)
To: edk2-devel, leif.lindholm, liming.gao, afish, ruiyu.ni,
michael.d.kinney, mw, feng.tian
Cc: Ard Biesheuvel
Add support for non-coherent DMA, either by performing explicit cache
maintenance when DMA mappings are aligned to the CPU's DMA buffer alignment,
or by bounce buffering via uncached mappings otherwise.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c | 14 +-
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf | 2 +
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c | 319 ++++++++++++++++++++
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h | 29 ++
4 files changed, 357 insertions(+), 7 deletions(-)
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
index ee765d7a5d9c..0fcf2b2ec1bf 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
@@ -16,6 +16,8 @@
#include <Protocol/DriverBinding.h>
+EFI_CPU_ARCH_PROTOCOL *mCpu;
+
//
// We only support the following device types
//
@@ -69,14 +71,7 @@ NonDiscoverablePciDeviceSupported (
return Status;
}
- //
- // Restricted to DMA coherent for now
- //
Status = EFI_UNSUPPORTED;
- if (Device->DmaType != NonDiscoverableDeviceDmaTypeCoherent) {
- goto CloseProtocol;
- }
-
for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++) {
if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices [Idx])) {
Status = EFI_SUCCESS;
@@ -224,6 +219,11 @@ NonDiscoverablePciDeviceDxeEntryPoint (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);
+ ASSERT_EFI_ERROR(Status);
+
return EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
index 996fe310e0e3..5faa8945134c 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
@@ -32,6 +32,7 @@ [Packages]
[LibraryClasses]
BaseMemoryLib
DebugLib
+ DxeServicesTableLib
MemoryAllocationLib
UefiBootServicesTableLib
UefiDriverEntryPoint
@@ -40,6 +41,7 @@ [LibraryClasses]
[Protocols]
gEfiPciIoProtocolGuid ## BY_START
gEdkiiNonDiscoverableDeviceProtocolGuid ## TO_START
+ gEfiCpuArchProtocolGuid ## CONSUMES
[Guids]
gEdkiiNonDiscoverableAhciDeviceGuid
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
index fd59267a8d66..5a4861a17717 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
@@ -15,6 +15,8 @@
#include "NonDiscoverablePciDeviceIo.h"
+#include <Library/DxeServicesTableLib.h>
+
#include <IndustryStandard/Acpi.h>
#include <Protocol/PciRootBridgeIo.h>
@@ -523,6 +525,316 @@ CoherentPciIoFreeBuffer (
return EFI_SUCCESS;
}
+STATIC
+EFI_STATUS
+NonCoherentPciIoFreeBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+ LIST_ENTRY *Entry;
+ EFI_STATUS Status;
+ NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;
+ BOOLEAN Found;
+
+ Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
+
+ Found = FALSE;
+
+ //
+ // Find the uncached allocation list entry associated
+ // with this allocation
+ //
+ for (Entry = Dev->UncachedAllocationList.ForwardLink;
+ Entry != &Dev->UncachedAllocationList;
+ Entry = Entry->ForwardLink) {
+
+ Alloc = BASE_CR (Entry, NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION, List);
+ if (Alloc->HostAddress == HostAddress && Alloc->NumPages == Pages) {
+ //
+ // We are freeing the exact allocation we were given
+ // before by AllocateBuffer()
+ //
+ Found = TRUE;
+ break;
+ }
+ }
+
+ if (!Found) {
+ ASSERT_EFI_ERROR (EFI_NOT_FOUND);
+ return EFI_NOT_FOUND;
+ }
+
+ RemoveEntryList (&Alloc->List);
+
+ Status = gDS->SetMemorySpaceAttributes (
+ (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
+ EFI_PAGES_TO_SIZE (Pages),
+ Alloc->Attributes);
+ if (EFI_ERROR (Status)) {
+ goto FreeAlloc;
+ }
+
+ //
+ // If we fail to restore the original attributes, it is better to leak the
+ // memory than to return it to the heap
+ //
+ FreePages (HostAddress, Pages);
+
+FreeAlloc:
+ FreePool (Alloc);
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+NonCoherentPciIoAllocateBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
+ EFI_STATUS Status;
+ UINT64 MemType;
+ NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;
+
+ Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
+
+ Status = CoherentPciIoAllocateBuffer (This, Type, MemoryType, Pages,
+ HostAddress, Attributes);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gDS->GetMemorySpaceDescriptor (
+ (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
+ &GcdDescriptor);
+ if (EFI_ERROR (Status)) {
+ goto FreeBuffer;
+ }
+
+ if ((GcdDescriptor.Capabilities & (EFI_MEMORY_WC | EFI_MEMORY_UC)) == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Set the preferred memory attributes
+ //
+ if ((Attributes & EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE) != 0 ||
+ (GcdDescriptor.Capabilities & EFI_MEMORY_UC) == 0) {
+ //
+ // Use write combining if it was requested, or if it is the only
+ // type supported by the region.
+ //
+ MemType = EFI_MEMORY_WC;
+ } else {
+ MemType = EFI_MEMORY_UC;
+ }
+
+ Alloc = AllocatePool (sizeof *Alloc);
+ if (Alloc == NULL) {
+ goto FreeBuffer;
+ }
+
+ Alloc->HostAddress = *HostAddress;
+ Alloc->NumPages = Pages;
+ Alloc->Attributes = GcdDescriptor.Attributes;
+
+ //
+ // Record this allocation in the linked list, so we
+ // can restore the memory space attributes later
+ //
+ InsertHeadList (&Dev->UncachedAllocationList, &Alloc->List);
+
+ Status = gDS->SetMemorySpaceAttributes (
+ (EFI_PHYSICAL_ADDRESS)(UINTN)*HostAddress,
+ EFI_PAGES_TO_SIZE (Pages),
+ MemType);
+ if (EFI_ERROR (Status)) {
+ goto RemoveList;
+ }
+
+ Status = mCpu->FlushDataCache (
+ mCpu,
+ (EFI_PHYSICAL_ADDRESS)(UINTN)*HostAddress,
+ EFI_PAGES_TO_SIZE (Pages),
+ EfiCpuFlushTypeInvalidate);
+ if (EFI_ERROR (Status)) {
+ goto RemoveList;
+ }
+
+ return EFI_SUCCESS;
+
+RemoveList:
+ RemoveEntryList (&Alloc->List);
+ FreePool (Alloc);
+
+FreeBuffer:
+ NonCoherentPciIoFreeBuffer (This, Pages, *HostAddress);
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+NonCoherentPciIoMap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+ EFI_STATUS Status;
+ NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;
+ UINTN AlignMask;
+ VOID *AllocAddress;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
+ BOOLEAN Bounce;
+
+ MapInfo = AllocatePool (sizeof *MapInfo);
+ if (MapInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ MapInfo->HostAddress = HostAddress;
+ MapInfo->Operation = Operation;
+ MapInfo->NumberOfBytes = *NumberOfBytes;
+
+ Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
+
+ //
+ // If this device does not support 64-bit DMA addressing, we need to allocate
+ // a bounce buffer and copy over the data in case HostAddress >= 4 GB.
+ //
+ Bounce = ((Dev->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0 &&
+ (UINTN)HostAddress + *NumberOfBytes > SIZE_4GB);
+
+ if (!Bounce) {
+ switch (Operation) {
+ case EfiPciIoOperationBusMasterRead:
+ case EfiPciIoOperationBusMasterWrite:
+ //
+ // For streaming DMA, it is sufficient if the buffer is aligned to
+ // the CPUs DMA buffer alignment.
+ //
+ AlignMask = mCpu->DmaBufferAlignment - 1;
+ if ((((UINTN) HostAddress | *NumberOfBytes) & AlignMask) == 0) {
+ break;
+ }
+ // fall through
+
+ case EfiPciIoOperationBusMasterCommonBuffer:
+ //
+ // Check whether the host address refers to an uncached mapping.
+ //
+ Status = gDS->GetMemorySpaceDescriptor (
+ (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
+ &GcdDescriptor);
+ if (EFI_ERROR (Status) ||
+ (GcdDescriptor.Attributes & (EFI_MEMORY_WB|EFI_MEMORY_WT)) != 0) {
+ Bounce = TRUE;
+ }
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+ }
+
+ if (Bounce) {
+ if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
+ Status = EFI_DEVICE_ERROR;
+ goto FreeMapInfo;
+ }
+
+ Status = NonCoherentPciIoAllocateBuffer (This, AllocateAnyPages,
+ EfiBootServicesData, EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),
+ &AllocAddress, EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE);
+ if (EFI_ERROR (Status)) {
+ goto FreeMapInfo;
+ }
+ MapInfo->AllocAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress;
+ if (Operation == EfiPciIoOperationBusMasterRead) {
+ gBS->CopyMem (AllocAddress, HostAddress, *NumberOfBytes);
+ }
+ *DeviceAddress = MapInfo->AllocAddress;
+ } else {
+ MapInfo->AllocAddress = 0;
+ *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
+
+ //
+ // We are not using a bounce buffer: the mapping is sufficiently
+ // aligned to allow us to simply flush the caches. Note that cleaning
+ // the caches is necessary for both data directions:
+ // - for bus master read, we want the latest data to be present
+ // in main memory
+ // - for bus master write, we don't want any stale dirty cachelines that
+ // may be written back unexpectedly, and clobber the data written to
+ // main memory by the device.
+ //
+ mCpu->FlushDataCache (mCpu, (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
+ *NumberOfBytes, EfiCpuFlushTypeWriteBack);
+ }
+
+ *Mapping = MapInfo;
+ return EFI_SUCCESS;
+
+FreeMapInfo:
+ FreePool (MapInfo);
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+NonCoherentPciIoUnmap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+{
+ NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;
+
+ if (Mapping == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ MapInfo = Mapping;
+ if (MapInfo->AllocAddress != 0) {
+ //
+ // We are using a bounce buffer: copy back the data if necessary,
+ // and free the buffer.
+ //
+ if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {
+ gBS->CopyMem (MapInfo->HostAddress, (VOID *)(UINTN)MapInfo->AllocAddress,
+ MapInfo->NumberOfBytes);
+ }
+ NonCoherentPciIoFreeBuffer (This,
+ EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),
+ (VOID *)(UINTN)MapInfo->AllocAddress);
+ } else {
+ //
+ // We are *not* using a bounce buffer: if this is a bus master write,
+ // we have to invalidate the caches so the CPU will see the uncached
+ // data written by the device.
+ //
+ if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {
+ mCpu->FlushDataCache (mCpu,
+ (EFI_PHYSICAL_ADDRESS)(UINTN)MapInfo->HostAddress,
+ MapInfo->NumberOfBytes, EfiCpuFlushTypeInvalidate);
+ }
+ }
+ FreePool (MapInfo);
+ return EFI_SUCCESS;
+}
STATIC
EFI_STATUS
@@ -715,6 +1027,13 @@ InitializePciIoProtocol (
// Copy protocol structure
CopyMem(&Dev->PciIo, &PciIoTemplate, sizeof PciIoTemplate);
+ if (Dev->Device->DmaType == NonDiscoverableDeviceDmaTypeNonCoherent) {
+ Dev->PciIo.AllocateBuffer = NonCoherentPciIoAllocateBuffer;
+ Dev->PciIo.FreeBuffer = NonCoherentPciIoFreeBuffer;
+ Dev->PciIo.Map = NonCoherentPciIoMap;
+ Dev->PciIo.Unmap = NonCoherentPciIoUnmap;
+ }
+
if (CompareGuid (Dev->Device->Type, &gEdkiiNonDiscoverableAhciDeviceGuid)) {
Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_MASS_STORAGE_AHCI;
Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_MASS_STORAGE_SATADPA;
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
index bc0a3d3258f9..449614862911 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
@@ -15,6 +15,8 @@
#ifndef __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
#define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
+#include <PiDxe.h>
+
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
@@ -25,6 +27,7 @@
#include <Protocol/ComponentName.h>
#include <Protocol/NonDiscoverableDevice.h>
+#include <Protocol/Cpu.h>
#include <Protocol/PciIo.h>
#define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I', 'D')
@@ -38,6 +41,27 @@
#define PCI_MAX_BARS 6
+extern EFI_CPU_ARCH_PROTOCOL *mCpu;
+
+typedef struct {
+ //
+ // The linked-list next pointer
+ //
+ LIST_ENTRY List;
+ //
+ // The address of the uncached allocation
+ //
+ VOID *HostAddress;
+ //
+ // The number of pages in the allocation
+ //
+ UINTN NumPages;
+ //
+ // The attributes of the allocation
+ //
+ UINT64 Attributes;
+} NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION;
+
typedef struct {
UINT32 Signature;
//
@@ -71,6 +95,11 @@ typedef struct {
// Whether this device has been enabled
//
BOOLEAN Enabled;
+ //
+ // Linked list to keep track of uncached allocations performed
+ // on behalf of this device
+ //
+ LIST_ENTRY UncachedAllocationList;
} NON_DISCOVERABLE_PCI_DEVICE;
VOID
--
2.7.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v4 5/5] Omap35xxPkg/PciEmulation: port to new non-discoverable device infrastructure
2016-11-25 15:42 [PATCH v4 0/5] MdeModulePkg: add support for non-discoverable devices Ard Biesheuvel
` (3 preceding siblings ...)
2016-11-25 15:42 ` [PATCH v4 4/5] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Ard Biesheuvel
@ 2016-11-25 15:42 ` Ard Biesheuvel
2016-11-27 10:18 ` [PATCH v4 0/5] MdeModulePkg: add support for non-discoverable devices Marcin Wojtas
5 siblings, 0 replies; 19+ messages in thread
From: Ard Biesheuvel @ 2016-11-25 15:42 UTC (permalink / raw)
To: edk2-devel, leif.lindholm, liming.gao, afish, ruiyu.ni,
michael.d.kinney, mw, feng.tian
Cc: Ard Biesheuvel
Move to the new non-discoverable device protocols for wiring the PCI based
EHCI controller driver to the non-discoverable EHCI controller found on the
OMAP 3530.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
BeagleBoardPkg/BeagleBoardPkg.dsc | 2 +
BeagleBoardPkg/BeagleBoardPkg.fdf | 1 +
Omap35xxPkg/Omap35xxPkg.dsc | 2 +-
Omap35xxPkg/PciEmulation/PciEmulation.c | 578 +-------------------
Omap35xxPkg/PciEmulation/PciEmulation.h | 292 ----------
Omap35xxPkg/PciEmulation/PciEmulation.inf | 16 +-
Omap35xxPkg/PciEmulation/PciRootBridgeIo.c | 306 -----------
7 files changed, 36 insertions(+), 1161 deletions(-)
diff --git a/BeagleBoardPkg/BeagleBoardPkg.dsc b/BeagleBoardPkg/BeagleBoardPkg.dsc
index f40095ac456b..2b0136ec3eec 100644
--- a/BeagleBoardPkg/BeagleBoardPkg.dsc
+++ b/BeagleBoardPkg/BeagleBoardPkg.dsc
@@ -184,6 +184,7 @@ [LibraryClasses.common.DXE_DRIVER]
DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
+ NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
[LibraryClasses.common.UEFI_APPLICATION]
ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
@@ -443,6 +444,7 @@ [Components.common]
# USB
#
Omap35xxPkg/PciEmulation/PciEmulation.inf
+ MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf {
<PcdsFixedAtBuild>
diff --git a/BeagleBoardPkg/BeagleBoardPkg.fdf b/BeagleBoardPkg/BeagleBoardPkg.fdf
index 42e097f64118..3d00355fff84 100644
--- a/BeagleBoardPkg/BeagleBoardPkg.fdf
+++ b/BeagleBoardPkg/BeagleBoardPkg.fdf
@@ -167,6 +167,7 @@ [FV.FvMain]
#
INF Omap35xxPkg/PciEmulation/PciEmulation.inf
+ INF MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
diff --git a/Omap35xxPkg/Omap35xxPkg.dsc b/Omap35xxPkg/Omap35xxPkg.dsc
index 4a3317f255f6..89a407049f31 100644
--- a/Omap35xxPkg/Omap35xxPkg.dsc
+++ b/Omap35xxPkg/Omap35xxPkg.dsc
@@ -79,7 +79,7 @@ [LibraryClasses.common]
[LibraryClasses.common.DXE_DRIVER]
DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
-
+ NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
[LibraryClasses.ARM]
NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
diff --git a/Omap35xxPkg/PciEmulation/PciEmulation.c b/Omap35xxPkg/PciEmulation/PciEmulation.c
index 17ea03ccf486..d17646a9ed58 100644
--- a/Omap35xxPkg/PciEmulation/PciEmulation.c
+++ b/Omap35xxPkg/PciEmulation/PciEmulation.c
@@ -1,6 +1,7 @@
/** @file
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2016, Linaro, Ltd. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -12,49 +13,27 @@
**/
-#include "PciEmulation.h"
+#include <PiDxe.h>
-EMBEDDED_EXTERNAL_DEVICE *gTPS65950;
-
-#define HOST_CONTROLLER_OPERATION_REG_SIZE 0x44
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/NonDiscoverableDeviceRegistrationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
-typedef struct {
- ACPI_HID_DEVICE_PATH AcpiDevicePath;
- PCI_DEVICE_PATH PciDevicePath;
- EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
-} EFI_PCI_IO_DEVICE_PATH;
+#include <Protocol/EmbeddedExternalDevice.h>
-typedef struct {
- UINT32 Signature;
- EFI_PCI_IO_DEVICE_PATH DevicePath;
- EFI_PCI_IO_PROTOCOL PciIoProtocol;
- PCI_TYPE00 *ConfigSpace;
- PCI_ROOT_BRIDGE RootBridge;
- UINTN Segment;
-} EFI_PCI_IO_PRIVATE_DATA;
+#include <TPS65950.h>
+#include <Omap3530/Omap3530.h>
-#define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32('p', 'c', 'i', 'o')
-#define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_PCI_IO_PRIVATE_DATA, PciIoProtocol, EFI_PCI_IO_PRIVATE_DATA_SIGNATURE)
+EMBEDDED_EXTERNAL_DEVICE *gTPS65950;
-EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate =
-{
- {
- { ACPI_DEVICE_PATH, ACPI_DP, { sizeof (ACPI_HID_DEVICE_PATH), 0 } },
- EISA_PNP_ID(0x0A03), // HID
- 0 // UID
- },
- {
- { HARDWARE_DEVICE_PATH, HW_PCI_DP, { sizeof (PCI_DEVICE_PATH), 0 } },
- 0,
- 0
- },
- { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} }
-};
+#define HOST_CONTROLLER_OPERATION_REG_SIZE 0x44
STATIC
-VOID
+EFI_STATUS
ConfigureUSBHost (
- VOID
+ NON_DISCOVERABLE_DEVICE *Device
)
{
EFI_STATUS Status;
@@ -103,454 +82,10 @@ ConfigureUSBHost (
Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data);
ASSERT_EFI_ERROR (Status);
-}
-
-
-EFI_STATUS
-PciIoPollMem (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINT64 Mask,
- IN UINT64 Value,
- IN UINT64 Delay,
- OUT UINT64 *Result
- )
-{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
-}
-
-EFI_STATUS
-PciIoPollIo (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINT64 Mask,
- IN UINT64 Value,
- IN UINT64 Delay,
- OUT UINT64 *Result
- )
-{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
-}
-
-EFI_STATUS
-PciIoMemRead (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
-
- return PciRootBridgeIoMemRead (&Private->RootBridge.Io,
- (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
- Private->ConfigSpace->Device.Bar[BarIndex] + Offset,
- Count,
- Buffer
- );
-}
-
-EFI_STATUS
-PciIoMemWrite (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
-
- return PciRootBridgeIoMemWrite (&Private->RootBridge.Io,
- (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
- Private->ConfigSpace->Device.Bar[BarIndex] + Offset,
- Count,
- Buffer
- );
-}
-
-EFI_STATUS
-PciIoIoRead (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
-}
-
-EFI_STATUS
-PciIoIoWrite (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 BarIndex,
- IN UINT64 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
-}
-
-/**
- Enable a PCI driver to read PCI controller registers in PCI configuration space.
-
- @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] Offset The offset 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 Offset.
-
- @param[in out] Buffer The destination buffer to store the results.
-
- @retval EFI_SUCCESS The data was read from the PCI controller.
- @retval EFI_INVALID_PARAMETER "Width" is invalid.
- @retval EFI_INVALID_PARAMETER "Buffer" is NULL.
-
-**/
-EFI_STATUS
-PciIoPciRead (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT32 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
- EFI_STATUS Status;
-
- if ((Width < 0) || (Width >= EfiPciIoWidthMaximum) || (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Status = PciRootBridgeIoMemRW (
- (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
- Count,
- TRUE,
- (PTR)(UINTN)Buffer,
- TRUE,
- (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset) //Fix me ConfigSpace
- );
-
- return Status;
-}
-
-/**
- Enable a PCI driver to write PCI controller registers in PCI configuration space.
-
- @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
- @param[in] Width Signifies the width of the memory operations.
- @param[in] Offset The offset 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 Offset.
-
- @param[in out] Buffer The source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from the PCI controller.
- @retval EFI_INVALID_PARAMETER "Width" is invalid.
- @retval EFI_INVALID_PARAMETER "Buffer" is NULL.
-
-**/
-EFI_STATUS
-PciIoPciWrite (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT32 Offset,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
-
- if ((Width < 0) || (Width >= EfiPciIoWidthMaximum) || (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
- Count,
- TRUE,
- (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset),
- TRUE,
- (PTR)(UINTN)Buffer
- );
-}
-
-EFI_STATUS
-PciIoCopyMem (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
- IN UINT8 DestBarIndex,
- IN UINT64 DestOffset,
- IN UINT8 SrcBarIndex,
- IN UINT64 SrcOffset,
- IN UINTN Count
- )
-{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
-}
-
-EFI_STATUS
-PciIoMap (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
- IN VOID *HostAddress,
- IN OUT UINTN *NumberOfBytes,
- OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
- OUT VOID **Mapping
- )
-{
- DMA_MAP_OPERATION DmaOperation;
-
- if (Operation == EfiPciIoOperationBusMasterRead) {
- DmaOperation = MapOperationBusMasterRead;
- } else if (Operation == EfiPciIoOperationBusMasterWrite) {
- DmaOperation = MapOperationBusMasterWrite;
- } else if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
- DmaOperation = MapOperationBusMasterCommonBuffer;
- } else {
- return EFI_INVALID_PARAMETER;
- }
- return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
-}
-EFI_STATUS
-PciIoUnmap (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN VOID *Mapping
- )
-{
- return DmaUnmap (Mapping);
-}
-
-/**
- Allocate pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer
- mapping.
-
- @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
- @param[in] Type This parameter is not used and must be ignored.
- @param[in] MemoryType The type of memory to allocate, EfiBootServicesData or
- EfiRuntimeServicesData.
- @param[in] Pages The number of pages to allocate.
- @param[out] HostAddress A pointer to store the base system memory address of
- the allocated range.
- @param[in] Attributes The requested bit mask of attributes for the allocated
- range. Only the attributes,
- EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE and
- EFI_PCI_ATTRIBUTE_MEMORY_CACHED may be used with this
- function. If any other bits are set, then EFI_UNSUPPORTED
- is returned. This function ignores this bit mask.
-
- @retval EFI_SUCCESS The requested memory pages were allocated.
- @retval EFI_INVALID_PARAMETER HostAddress is NULL.
- @retval EFI_INVALID_PARAMETER MemoryType is invalid.
- @retval EFI_UNSUPPORTED Attributes is unsupported.
- @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
-
-**/
-EFI_STATUS
-PciIoAllocateBuffer (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_ALLOCATE_TYPE Type,
- IN EFI_MEMORY_TYPE MemoryType,
- IN UINTN Pages,
- OUT VOID **HostAddress,
- IN UINT64 Attributes
- )
-{
- if (Attributes &
- (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE |
- EFI_PCI_ATTRIBUTE_MEMORY_CACHED ))) {
- return EFI_UNSUPPORTED;
- }
-
- return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
-}
-
-
-EFI_STATUS
-PciIoFreeBuffer (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN UINTN Pages,
- IN VOID *HostAddress
- )
-{
- return DmaFreeBuffer (Pages, HostAddress);
-}
-
-
-EFI_STATUS
-PciIoFlush (
- IN EFI_PCI_IO_PROTOCOL *This
- )
-{
return EFI_SUCCESS;
}
-/**
- Retrieves this PCI controller's current PCI bus number, device number, and function number.
-
- @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
- @param[out] SegmentNumber The PCI controller's current PCI segment number.
- @param[out] BusNumber The PCI controller's current PCI bus number.
- @param[out] DeviceNumber The PCI controller's current PCI device number.
- @param[out] FunctionNumber The PCI controller's current PCI function number.
-
- @retval EFI_SUCCESS The PCI controller location was returned.
- @retval EFI_INVALID_PARAMETER At least one out of the four output parameters is
- a NULL pointer.
-**/
-EFI_STATUS
-PciIoGetLocation (
- IN EFI_PCI_IO_PROTOCOL *This,
- OUT UINTN *SegmentNumber,
- OUT UINTN *BusNumber,
- OUT UINTN *DeviceNumber,
- OUT UINTN *FunctionNumber
- )
-{
- EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
-
- if ((SegmentNumber == NULL) || (BusNumber == NULL) ||
- (DeviceNumber == NULL) || (FunctionNumber == NULL) ) {
- return EFI_INVALID_PARAMETER;
- }
-
- *SegmentNumber = Private->Segment;
- *BusNumber = 0xff;
- *DeviceNumber = 0;
- *FunctionNumber = 0;
-
- return EFI_SUCCESS;
-}
-
-/**
- Performs an operation on the attributes that this PCI controller supports.
-
- The operations include getting the set of supported attributes, retrieving
- the current attributes, setting the current attributes, enabling attributes,
- and disabling attributes.
-
- @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
- @param[in] Operation The operation to perform on the attributes for this
- PCI controller.
- @param[in] Attributes The mask of attributes that are used for Set,
- Enable and Disable operations.
- @param[out] Result A pointer to the result mask of attributes that are
- returned for the Get and Supported operations. This
- is an optional parameter that may be NULL for the
- Set, Enable, and Disable operations.
-
- @retval EFI_SUCCESS The operation on the PCI controller's
- attributes was completed. If the operation
- was Get or Supported, then the attribute mask
- is returned in Result.
- @retval EFI_INVALID_PARAMETER Operation is greater than or equal to
- EfiPciIoAttributeOperationMaximum.
- @retval EFI_INVALID_PARAMETER Operation is Get and Result is NULL.
- @retval EFI_INVALID_PARAMETER Operation is Supported and Result is NULL.
-
-**/
-EFI_STATUS
-PciIoAttributes (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
- IN UINT64 Attributes,
- OUT UINT64 *Result OPTIONAL
- )
-{
- switch (Operation) {
- case EfiPciIoAttributeOperationGet:
- case EfiPciIoAttributeOperationSupported:
- if (Result == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // We are not a real PCI device so just say things we kind of do
- //
- *Result = EFI_PCI_DEVICE_ENABLE;
- break;
-
- case EfiPciIoAttributeOperationSet:
- case EfiPciIoAttributeOperationEnable:
- case EfiPciIoAttributeOperationDisable:
- if (Attributes & (~EFI_PCI_DEVICE_ENABLE)) {
- return EFI_UNSUPPORTED;
- }
- // Since we are not a real PCI device no enable/set or disable operations exist.
- return EFI_SUCCESS;
-
- default:
- return EFI_INVALID_PARAMETER;
- };
- return EFI_SUCCESS;
-}
-
-EFI_STATUS
-PciIoGetBarAttributes (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN UINT8 BarIndex,
- OUT UINT64 *Supports, OPTIONAL
- OUT VOID **Resources OPTIONAL
- )
-{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
-}
-
-EFI_STATUS
-PciIoSetBarAttributes (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN UINT64 Attributes,
- IN UINT8 BarIndex,
- IN OUT UINT64 *Offset,
- IN OUT UINT64 *Length
- )
-{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
-}
-
-EFI_PCI_IO_PROTOCOL PciIoTemplate =
-{
- PciIoPollMem,
- PciIoPollIo,
- { PciIoMemRead, PciIoMemWrite },
- { PciIoIoRead, PciIoIoWrite },
- { PciIoPciRead, PciIoPciWrite },
- PciIoCopyMem,
- PciIoMap,
- PciIoUnmap,
- PciIoAllocateBuffer,
- PciIoFreeBuffer,
- PciIoFlush,
- PciIoGetLocation,
- PciIoAttributes,
- PciIoGetBarAttributes,
- PciIoSetBarAttributes,
- 0,
- 0
-};
-
EFI_STATUS
EFIAPI
PciEmulationEntryPoint (
@@ -558,76 +93,21 @@ PciEmulationEntryPoint (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
- EFI_STATUS Status;
- EFI_HANDLE Handle;
- EFI_PCI_IO_PRIVATE_DATA *Private;
UINT8 CapabilityLength;
UINT8 PhysicalPorts;
- UINTN Count;
-
-
- //Configure USB host for OMAP3530.
- ConfigureUSBHost();
-
- // Create a private structure
- Private = AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA));
- if (Private == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- return Status;
- }
-
- Private->Signature = EFI_PCI_IO_PRIVATE_DATA_SIGNATURE; // Fill in signature
- Private->RootBridge.Signature = PCI_ROOT_BRIDGE_SIGNATURE; // Fake Root Bridge structure needs a signature too
- Private->RootBridge.MemoryStart = USB_EHCI_HCCAPBASE; // Get the USB capability register base
- Private->Segment = 0; // Default to segment zero
-
- // Find out the capability register length and number of physical ports.
- CapabilityLength = MmioRead8(Private->RootBridge.MemoryStart);
- PhysicalPorts = (MmioRead32 (Private->RootBridge.MemoryStart + 0x4)) & 0x0000000F;
-
- // Calculate the total size of the USB registers.
- Private->RootBridge.MemorySize = CapabilityLength + (HOST_CONTROLLER_OPERATION_REG_SIZE + ((4 * PhysicalPorts) - 1));
-
- // Enable Port Power bit in Port status and control registers in EHCI register space.
- // Port Power Control (PPC) bit in the HCSPARAMS register is already set which indicates
- // host controller implementation includes port power control.
- for (Count = 0; Count < PhysicalPorts; Count++) {
- MmioOr32 ((Private->RootBridge.MemoryStart + CapabilityLength + HOST_CONTROLLER_OPERATION_REG_SIZE + 4*Count), 0x00001000);
- }
-
- // Create fake PCI config space.
- Private->ConfigSpace = AllocateZeroPool(sizeof(PCI_TYPE00));
- if (Private->ConfigSpace == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- FreePool(Private);
- return Status;
- }
-
- // Configure PCI config space
- Private->ConfigSpace->Hdr.VendorId = 0xFFFF; // Invalid vendor Id as it is not an actual device.
- Private->ConfigSpace->Hdr.DeviceId = 0x0000; // Not relevant as the vendor id is not valid.
- Private->ConfigSpace->Hdr.ClassCode[0] = 0x20;
- Private->ConfigSpace->Hdr.ClassCode[1] = 0x03;
- Private->ConfigSpace->Hdr.ClassCode[2] = 0x0C;
- Private->ConfigSpace->Device.Bar[0] = Private->RootBridge.MemoryStart;
-
- Handle = NULL;
-
- // Unique device path.
- CopyMem(&Private->DevicePath, &PciIoDevicePathTemplate, sizeof(PciIoDevicePathTemplate));
- Private->DevicePath.AcpiDevicePath.UID = 0;
-
- // Copy protocol structure
- CopyMem(&Private->PciIoProtocol, &PciIoTemplate, sizeof(PciIoTemplate));
-
- Status = gBS->InstallMultipleProtocolInterfaces(&Handle,
- &gEfiPciIoProtocolGuid, &Private->PciIoProtocol,
- &gEfiDevicePathProtocolGuid, &Private->DevicePath,
- NULL);
- if (EFI_ERROR(Status)) {
- DEBUG((EFI_D_ERROR, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces() failed.\n"));
- }
-
- return Status;
+ UINTN MemorySize;
+
+ CapabilityLength = MmioRead8 (USB_EHCI_HCCAPBASE);
+ PhysicalPorts = MmioRead32 (USB_EHCI_HCCAPBASE + 0x4) & 0x0000000F;
+ MemorySize = CapabilityLength + HOST_CONTROLLER_OPERATION_REG_SIZE +
+ 4 * PhysicalPorts - 1;
+
+ return RegisterNonDiscoverableMmioDevice (
+ NonDiscoverableDeviceTypeEhci,
+ NonDiscoverableDeviceDmaTypeNonCoherent,
+ ConfigureUSBHost,
+ NULL,
+ 1,
+ USB_EHCI_HCCAPBASE, MemorySize
+ );
}
-
diff --git a/Omap35xxPkg/PciEmulation/PciEmulation.h b/Omap35xxPkg/PciEmulation/PciEmulation.h
deleted file mode 100644
index d5ee04318939..000000000000
--- a/Omap35xxPkg/PciEmulation/PciEmulation.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/** @file
-
- Copyright (c) 2008 - 2009, Apple Inc. 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
-
- 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_ROOT_BRIDGE_H_
-#define _PCI_ROOT_BRIDGE_H_
-
-#include <PiDxe.h>
-
-#include <TPS65950.h>
-
-#include <Library/BaseLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/DebugLib.h>
-#include <Library/DxeServicesTableLib.h>
-#include <Library/IoLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/PciLib.h>
-#include <Library/UefiLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/OmapDmaLib.h>
-#include <Library/DmaLib.h>
-
-#include <Protocol/EmbeddedExternalDevice.h>
-#include <Protocol/DevicePath.h>
-#include <Protocol/PciIo.h>
-#include <Protocol/PciRootBridgeIo.h>
-#include <Protocol/PciHostBridgeResourceAllocation.h>
-
-#include <IndustryStandard/Pci22.h>
-#include <IndustryStandard/Acpi.h>
-
-#include <Omap3530/Omap3530.h>
-
-
-
-#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL
-#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL
-#define EFI_RESOURCE_SATISFIED 0x0000000000000000ULL
-
-
-typedef struct {
- ACPI_HID_DEVICE_PATH AcpiDevicePath;
- EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
-} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
-
-
-#define ACPI_CONFIG_IO 0
-#define ACPI_CONFIG_MMIO 1
-#define ACPI_CONFIG_BUS 2
-
-typedef struct {
- EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR Desc[3];
- EFI_ACPI_END_TAG_DESCRIPTOR EndDesc;
-} ACPI_CONFIG_INFO;
-
-
-#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32 ('P', 'c', 'i', 'F')
-
-typedef struct {
- UINT32 Signature;
- EFI_HANDLE Handle;
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
- EFI_PCI_ROOT_BRIDGE_DEVICE_PATH DevicePath;
-
- UINT8 StartBus;
- UINT8 EndBus;
- UINT16 Type;
- UINT32 MemoryStart;
- UINT32 MemorySize;
- UINTN IoOffset;
- UINT32 IoStart;
- UINT32 IoSize;
- UINT64 PciAttributes;
-
- ACPI_CONFIG_INFO *Config;
-
-} PCI_ROOT_BRIDGE;
-
-
-#define INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) CR (a, PCI_ROOT_BRIDGE, Io, PCI_ROOT_BRIDGE_SIGNATURE)
-
-
-typedef union {
- UINT8 volatile *buf;
- UINT8 volatile *ui8;
- UINT16 volatile *ui16;
- UINT32 volatile *ui32;
- UINT64 volatile *ui64;
- UINTN volatile ui;
-} PTR;
-
-
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPollMem (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINT64 Mask,
- IN UINT64 Value,
- IN UINT64 Delay,
- OUT UINT64 *Result
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPollIo (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINT64 Mask,
- IN UINT64 Value,
- IN UINT64 Delay,
- OUT UINT64 *Result
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMemRead (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMemWrite (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoIoRead (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 UserAddress,
- IN UINTN Count,
- IN OUT VOID *UserBuffer
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoIoWrite (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 UserAddress,
- IN UINTN Count,
- IN OUT VOID *UserBuffer
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoCopyMem (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 DestAddress,
- IN UINT64 SrcAddress,
- IN UINTN Count
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPciRead (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPciWrite (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMap (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
- IN VOID *HostAddress,
- IN OUT UINTN *NumberOfBytes,
- OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
- OUT VOID **Mapping
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoUnmap (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN VOID *Mapping
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoAllocateBuffer (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_ALLOCATE_TYPE Type,
- IN EFI_MEMORY_TYPE MemoryType,
- IN UINTN Pages,
- OUT VOID **HostAddress,
- IN UINT64 Attributes
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoFreeBuffer (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN UINTN Pages,
- OUT VOID *HostAddress
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoFlush (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoGetAttributes (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- OUT UINT64 *Supported,
- OUT UINT64 *Attributes
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoSetAttributes (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN UINT64 Attributes,
- IN OUT UINT64 *ResourceBase,
- IN OUT UINT64 *ResourceLength
- );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoConfiguration (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- OUT VOID **Resources
- );
-
-//
-// Private Function Prototypes
-//
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMemRW (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINTN Count,
- IN BOOLEAN InStrideFlag,
- IN PTR In,
- IN BOOLEAN OutStrideFlag,
- OUT PTR Out
- );
-
-BOOLEAN
-PciIoMemAddressValid (
- IN EFI_PCI_IO_PROTOCOL *This,
- IN UINT64 Address
- );
-
-EFI_STATUS
-EmulatePciIoForEhci (
- INTN MvPciIfMaxIf
- );
-
-#endif
-
diff --git a/Omap35xxPkg/PciEmulation/PciEmulation.inf b/Omap35xxPkg/PciEmulation/PciEmulation.inf
index 2180bb49898d..4df9c505e8cd 100644
--- a/Omap35xxPkg/PciEmulation/PciEmulation.inf
+++ b/Omap35xxPkg/PciEmulation/PciEmulation.inf
@@ -22,33 +22,23 @@ [Defines]
ENTRY_POINT = PciEmulationEntryPoint
[Sources.common]
- PciRootBridgeIo.c
PciEmulation.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
- IntelFrameworkPkg/IntelFrameworkPkg.dec
- ArmPkg/ArmPkg.dec
EmbeddedPkg/EmbeddedPkg.dec
Omap35xxPkg/Omap35xxPkg.dec
[LibraryClasses]
BaseLib
- DxeServicesTableLib
- UefiLib
+ DebugLib
+ IoLib
+ NonDiscoverableDeviceRegistrationLib
UefiBootServicesTableLib
UefiDriverEntryPoint
- UefiRuntimeServicesTableLib
- IoLib
- OmapDmaLib
- DmaLib
[Protocols]
- gEfiPciRootBridgeIoProtocolGuid
- gEfiDevicePathProtocolGuid
- gEfiPciHostBridgeResourceAllocationProtocolGuid
- gEfiPciIoProtocolGuid
gEmbeddedExternalDeviceProtocolGuid
[Depex]
diff --git a/Omap35xxPkg/PciEmulation/PciRootBridgeIo.c b/Omap35xxPkg/PciEmulation/PciRootBridgeIo.c
deleted file mode 100644
index e8635ed88d91..000000000000
--- a/Omap35xxPkg/PciEmulation/PciRootBridgeIo.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/** @file
-
- Copyright (c) 2008 - 2009, Apple Inc. 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
-
- 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 "PciEmulation.h"
-
-BOOLEAN
-PciRootBridgeMemAddressValid (
- IN PCI_ROOT_BRIDGE *Private,
- IN UINT64 Address
- )
-{
- if ((Address >= Private->MemoryStart) && (Address < (Private->MemoryStart + Private->MemorySize))) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-EFI_STATUS
-PciRootBridgeIoMemRW (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINTN Count,
- IN BOOLEAN InStrideFlag,
- IN PTR In,
- IN BOOLEAN OutStrideFlag,
- OUT PTR Out
- )
-{
- UINTN Stride;
- UINTN InStride;
- UINTN OutStride;
-
-
- Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
- Stride = (UINTN)1 << Width;
- InStride = InStrideFlag ? Stride : 0;
- OutStride = OutStrideFlag ? Stride : 0;
-
- //
- // Loop for each iteration and move the data
- //
- switch (Width) {
- case EfiPciWidthUint8:
- for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
- *In.ui8 = *Out.ui8;
- }
- break;
- case EfiPciWidthUint16:
- for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
- *In.ui16 = *Out.ui16;
- }
- break;
- case EfiPciWidthUint32:
- for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
- *In.ui32 = *Out.ui32;
- }
- break;
- default:
- return EFI_INVALID_PARAMETER;
- }
-
- return EFI_SUCCESS;
-}
-
-EFI_STATUS
-PciRootBridgeIoPciRW (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN BOOLEAN Write,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 UserAddress,
- IN UINTN Count,
- IN OUT VOID *UserBuffer
- )
-{
- return EFI_SUCCESS;
-}
-
-/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param Width Signifies the width of the memory operations.
- @param Address The base address of the memory operations.
- @param Count The number of memory operations to perform.
- @param Buffer For read operations, the destination buffer to store the results. For write
- operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
-
-**/
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMemRead (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- PCI_ROOT_BRIDGE *Private;
- UINTN AlignMask;
- PTR In;
- PTR Out;
-
- if ( Buffer == NULL ) {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
-
- if (!PciRootBridgeMemAddressValid (Private, Address)) {
- return EFI_INVALID_PARAMETER;
- }
-
- AlignMask = (1 << (Width & 0x03)) - 1;
- if (Address & AlignMask) {
- return EFI_INVALID_PARAMETER;
- }
-
- In.buf = Buffer;
- Out.buf = (VOID *)(UINTN) Address;
-
- switch (Width) {
- case EfiPciWidthUint8:
- case EfiPciWidthUint16:
- case EfiPciWidthUint32:
- case EfiPciWidthUint64:
- return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
-
- case EfiPciWidthFifoUint8:
- case EfiPciWidthFifoUint16:
- case EfiPciWidthFifoUint32:
- case EfiPciWidthFifoUint64:
- return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
-
- case EfiPciWidthFillUint8:
- case EfiPciWidthFillUint16:
- case EfiPciWidthFillUint32:
- case EfiPciWidthFillUint64:
- return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
-
- default:
- break;
- }
-
- return EFI_INVALID_PARAMETER;
-}
-
-
-
-/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param Width Signifies the width of the memory operations.
- @param Address The base address of the memory operations.
- @param Count The number of memory operations to perform.
- @param Buffer For read operations, the destination buffer to store the results. For write
- operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
-
-**/
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMemWrite (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- PCI_ROOT_BRIDGE *Private;
- UINTN AlignMask;
- PTR In;
- PTR Out;
-
- if ( Buffer == NULL ) {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
-
- if (!PciRootBridgeMemAddressValid (Private, Address)) {
- return EFI_INVALID_PARAMETER;
- }
-
- AlignMask = (1 << (Width & 0x03)) - 1;
- if (Address & AlignMask) {
- return EFI_INVALID_PARAMETER;
- }
-
- In.buf = (VOID *)(UINTN) Address;
- Out.buf = Buffer;
-
- switch (Width) {
- case EfiPciWidthUint8:
- case EfiPciWidthUint16:
- case EfiPciWidthUint32:
- case EfiPciWidthUint64:
- return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
-
- case EfiPciWidthFifoUint8:
- case EfiPciWidthFifoUint16:
- case EfiPciWidthFifoUint32:
- case EfiPciWidthFifoUint64:
- return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
-
- case EfiPciWidthFillUint8:
- case EfiPciWidthFillUint16:
- case EfiPciWidthFillUint32:
- case EfiPciWidthFillUint64:
- return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
-
- default:
- break;
- }
-
- return EFI_INVALID_PARAMETER;
-}
-
-/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param Width Signifies the width of the memory operations.
- @param Address The base address of the memory operations.
- @param Count The number of memory operations to perform.
- @param Buffer For read operations, the destination buffer to store the results. For write
- operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
-
-**/
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPciRead (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- if (Buffer == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- return PciRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
-}
-
-
-
-/**
- Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
- @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
- @param Width Signifies the width of the memory operations.
- @param Address The base address of the memory operations.
- @param Count The number of memory operations to perform.
- @param Buffer For read operations, the destination buffer to store the results. For write
- operations, the source buffer to write data from.
-
- @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
-
-**/
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPciWrite (
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- if (Buffer == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- return PciRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
-}
-
-
--
2.7.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v4 0/5] MdeModulePkg: add support for non-discoverable devices
2016-11-25 15:42 [PATCH v4 0/5] MdeModulePkg: add support for non-discoverable devices Ard Biesheuvel
` (4 preceding siblings ...)
2016-11-25 15:42 ` [PATCH v4 5/5] Omap35xxPkg/PciEmulation: port to new non-discoverable device infrastructure Ard Biesheuvel
@ 2016-11-27 10:18 ` Marcin Wojtas
5 siblings, 0 replies; 19+ messages in thread
From: Marcin Wojtas @ 2016-11-27 10:18 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: edk2-devel-01, Leif Lindholm, Gao, Liming, afish, Ni, Ruiyu,
Kinney, Michael D, Tian, Feng
Hi Ard,
Solution works on Marvell Armada 7040, tested SATA/USB/SD/eMMC.
Tested-by: Marcin Wojtas <mw@semihalf.com>
Best regards,
Marcin
2016-11-25 16:42 GMT+01:00 Ard Biesheuvel <ard.biesheuvel@linaro.org>:
> The rationale for this series is the fact that many ARM platforms implement
> some form of PCI 'emulation', to allow non-discoverable devices that implement
> standardized host controller interfaces (i.e., EHCI, AHCI) to be controlled by
> the generic EDK2 drivers, which are layered on top of the PCI I/O protocols
> (even though the respective host controller specifications don't mandate that)
>
> There are a couple of problems with that approach:
> - Most implementations are based on the original code created for BeagleBoard,
> which is a 32-bit platform. Unlike x86, which usually does not perform PCI
> DMA above 4 GB, the ARM ecosystem is much more heterogeneous, and platforms
> that have memory both above and below the 4 GB mark may ship with, e.g., EHCI
> controllers that do not implement 64-bit DMA addressing.
> - Implementations depend on the DmaLib library class in EmbeddedPkg, of which
> coherent and non-coherent implementations exists. However, both types of
> devices may appear on a single platform, requiring several instances of the
> same driver.
> - Existing implementations do not follow the UEFI driver model, but instantiate
> a fixed number of PCI I/O protocol handles, and bring up all the devices when
> doing so. However, the UEFI philosophy is to only instantiate (and thus
> initialize) devices that are involved in booting.
>
> So instead, let's define a base protocol that simply asserts the presence of
> a certain kind of device at a certain memory offset, allowing platforms to
> instantiate any number of these statically, and leave it to post-DXE driver
> dispatch to actually bind the drivers as usual. This is implemented in patch #1.
> Note that it includes an AMBA device type, which we intend to use in the future
> to move ARM AMBA drivers to the UEFI driver model as well (i.e., LCD controller,
> SD/MMC controller)
>
> Patch #2 implements a utility library to register non-discoverable devices.
>
> Patch #3 implements the UEFI driver that instantiates PCI I/O protocol handles
> for non-discoverable devices that we know can be driven by a generic driver in
> EDK2. The initial version implements coherent DMA only.
>
> Patch #4 implements non-coherent DMA for the driver added in patch #3.
>
> Patch #5 is included for reference. It ports the BeagleBoard platform to the
> new driver stack.
>
> Changes in v4:
> - use GUIDs to describe the type of device (AHCI, EHCI, etc), rathen than en
> enum, to make the protocol more flexible and futureproof
> - revert special handling of SDHCI, which does not map cleanly onto a single
> PCI device (SDHCI-PCI may expose several slots, each of which is a full
> fledged implementation of the SDHCI spec, but the EDK2 SDHCI driver does
> not model those as a bus)
> - don't treat 64-bit BARs as 2 logical BARs
>
> Branch can be found here
> https://git.linaro.org/people/ard.biesheuvel/uefi-next.git/log/?h=non-discoverable-pci-v4
>
> Changes in v3:
> - Modified the base protocol to describe any number of resources using ACPI
> resource descriptors. The current crop of targeted peripherals does not
> require that, but it allows for much more flexibility in the future. This
> also means that the MMIO region sizes are no longer hard-coded base on the
> controller type (EHCI, AHCI, etc) but need to be declared when the devices
> are registered.
> - Update the registration library API to allow multiple MMIO regions to be
> declared.
> - When performing uncached allocations, record the original memory region
> attributes so we can restore them correctly on free.
> - Some fixes in the 4GB boundary checks for Map/Unmap
> - Rename gNonDiscoverableDeviceProtocolGuid to
> gEdkiiNonDiscoverableDeviceProtocolGuid
>
> Ard Biesheuvel (5):
> MdeModulePkg: introduce non-discoverable device protocol
> MdeModulePkg: introduce helper library to register non-discoverable
> devices
> MdeModulePkg: implement generic PCI I/O driver for non-discoverable
> devices
> MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent
> DMA
> Omap35xxPkg/PciEmulation: port to new non-discoverable device
> infrastructure
>
> BeagleBoardPkg/BeagleBoardPkg.dsc | 2 +
> BeagleBoardPkg/BeagleBoardPkg.fdf | 1 +
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c | 75 ++
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c | 235 +++++
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf | 54 +
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c | 1116 ++++++++++++++++++++
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h | 113 ++
> MdeModulePkg/Include/Guid/NonDiscoverableDevice.h | 58 +
> MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h | 62 ++
> MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 77 ++
> MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c | 204 ++++
> MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf | 46 +
> MdeModulePkg/MdeModulePkg.dec | 18 +
> MdeModulePkg/MdeModulePkg.dsc | 3 +
> Omap35xxPkg/Omap35xxPkg.dsc | 2 +-
> Omap35xxPkg/PciEmulation/PciEmulation.c | 578 +---------
> Omap35xxPkg/PciEmulation/PciEmulation.h | 292 -----
> Omap35xxPkg/PciEmulation/PciEmulation.inf | 16 +-
> Omap35xxPkg/PciEmulation/PciRootBridgeIo.c | 306 ------
> 19 files changed, 2097 insertions(+), 1161 deletions(-)
> create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c
> create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
> create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
> create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
> create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
> create mode 100644 MdeModulePkg/Include/Guid/NonDiscoverableDevice.h
> create mode 100644 MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h
> create mode 100644 MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
> create mode 100644 MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c
> create mode 100644 MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
> delete mode 100644 Omap35xxPkg/PciEmulation/PciEmulation.h
> delete mode 100644 Omap35xxPkg/PciEmulation/PciRootBridgeIo.c
>
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4 3/5] MdeModulePkg: implement generic PCI I/O driver for non-discoverable devices
2016-11-25 15:42 ` [PATCH v4 3/5] MdeModulePkg: implement generic PCI I/O driver for " Ard Biesheuvel
@ 2016-11-28 1:56 ` Ni, Ruiyu
2016-11-30 14:06 ` Leif Lindholm
0 siblings, 1 reply; 19+ messages in thread
From: Ni, Ruiyu @ 2016-11-28 1:56 UTC (permalink / raw)
To: Ard Biesheuvel, edk2-devel@lists.01.org, leif.lindholm@linaro.org,
Gao, Liming, afish@apple.com, Kinney, Michael D, mw@semihalf.com,
Tian, Feng
Ard,
I found you removed the SDHCI special handling code.
Only one minor comments in below. (you could search RShiftU64 in below).
Reviewed-by: Ruiyu Ni <Ruiyu.ni@intel.com>
Thanks/Ray
> -----Original Message-----
> From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
> Sent: Friday, November 25, 2016 11:42 PM
> To: edk2-devel@lists.01.org; leif.lindholm@linaro.org; Gao, Liming
> <liming.gao@intel.com>; afish@apple.com; Ni, Ruiyu <ruiyu.ni@intel.com>;
> Kinney, Michael D <michael.d.kinney@intel.com>; mw@semihalf.com; Tian,
> Feng <feng.tian@intel.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Subject: [PATCH v4 3/5] MdeModulePkg: implement generic PCI I/O driver
> for non-discoverable devices
>
> This implements support for non-discoverable PCI compatible devices, i.e,
> devices that are not on a PCI bus but that can be controlled by generic PCI
> drivers in EDK2.
>
> This is implemented as a UEFI driver, which means we take full advantage of
> the UEFI driver model, and only instantiate those devices that are necessary
> for booting.
>
> Care is taken to deal with DMA addressing limitations: DMA mappings and
> allocations are moved below 4 GB if the PCI driver has not informed us that
> the device being driven is 64-bit DMA capable. DMA is implemented as
> coherent, support for non-coherent DMA is implemented by a subsequent
> patch.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c
> | 75 ++
>
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
> DeviceDxe.c | 235 ++++++
>
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
> DeviceDxe.inf | 52 ++
>
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
> DeviceIo.c | 797 ++++++++++++++++++++
>
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
> DeviceIo.h | 84 +++
> MdeModulePkg/MdeModulePkg.dsc | 1 +
> 6 files changed, 1244 insertions(+)
>
> diff --git
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentNam
> e.c
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentNam
> e.c
> new file mode 100644
> index 000000000000..6e51d00fe434
> --- /dev/null
> +++
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentNam
> e.c
> @@ -0,0 +1,75 @@
> +/** @file
> +
> + Copyright (C) 2016, Linaro Ltd. 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
> +
> + 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 "NonDiscoverablePciDeviceIo.h"
> +
> +//
> +// The purpose of the following scaffolding
> +(EFI_COMPONENT_NAME_PROTOCOL and //
> EFI_COMPONENT_NAME2_PROTOCOL
> +implementation) is to format the driver's name // in English, for
> +display on standard console devices. This is recommended for // UEFI
> +drivers that follow the UEFI Driver Model. Refer to the Driver Writer's //
> Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
> +//
> +
> +STATIC
> +EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
> + { "eng;en", L"PCI I/O protocol emulation driver for non-discoverable
> devices" },
> + { NULL, NULL }
> +};
> +
> +EFI_COMPONENT_NAME_PROTOCOL gComponentName;
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonDiscoverablePciGetDriverName (
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
> + IN CHAR8 *Language,
> + OUT CHAR16 **DriverName
> + )
> +{
> + return LookupUnicodeString2 (
> + Language,
> + This->SupportedLanguages,
> + mDriverNameTable,
> + DriverName,
> + (BOOLEAN)(This == &gComponentName) // Iso639Language
> + );
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonDiscoverablePciGetDeviceName (
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
> + IN EFI_HANDLE DeviceHandle,
> + IN EFI_HANDLE ChildHandle,
> + IN CHAR8 *Language,
> + OUT CHAR16 **ControllerName
> + )
> +{
> + return EFI_UNSUPPORTED;
> +}
> +
> +EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
> + &NonDiscoverablePciGetDriverName,
> + &NonDiscoverablePciGetDeviceName,
> + "eng" // SupportedLanguages, ISO 639-2 language codes };
> +
> +EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
> + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)
> &NonDiscoverablePciGetDriverName,
> + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)
> +&NonDiscoverablePciGetDeviceName,
> + "en" // SupportedLanguages, RFC 4646 language codes };
> diff --git
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.c
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.c
> new file mode 100644
> index 000000000000..ee765d7a5d9c
> --- /dev/null
> +++
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> Pc
> +++ iDeviceDxe.c
> @@ -0,0 +1,235 @@
> +/** @file
> +
> + Copyright (C) 2016, Linaro Ltd. 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
> +
> + 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 "NonDiscoverablePciDeviceIo.h"
> +
> +#include <Protocol/DriverBinding.h>
> +
> +//
> +// We only support the following device types // STATIC CONST EFI_GUID
> +* CONST SupportedNonDiscoverableDevices [] = {
> + &gEdkiiNonDiscoverableAhciDeviceGuid,
> + &gEdkiiNonDiscoverableEhciDeviceGuid,
> + &gEdkiiNonDiscoverableNvmeDeviceGuid,
> + &gEdkiiNonDiscoverableOhciDeviceGuid,
> + &gEdkiiNonDiscoverableSdhciDeviceGuid,
> + &gEdkiiNonDiscoverableUfsDeviceGuid,
> + &gEdkiiNonDiscoverableUhciDeviceGuid,
> + &gEdkiiNonDiscoverableXhciDeviceGuid,
> +};
> +
> +//
> +// Probe, start and stop functions of this driver, called by the DXE
> +core for // specific devices.
> +//
> +// The following specifications document these interfaces:
> +// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding
> +Protocol // - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding
> +Protocol // // The implementation follows:
> +// - Driver Writer's Guide for UEFI 2.3.1 v1.01
> +// - 5.1.3.4 OpenProtocol() and CloseProtocol()
> +// - UEFI Spec 2.3.1 + Errata C
> +// - 6.3 Protocol Handler Services
> +//
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonDiscoverablePciDeviceSupported (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE DeviceHandle,
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
> + )
> +{
> + NON_DISCOVERABLE_DEVICE *Device;
> + EFI_STATUS Status;
> + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
> + INTN Idx;
> +
> + Status = gBS->OpenProtocol (DeviceHandle,
> + &gEdkiiNonDiscoverableDeviceProtocolGuid, (VOID **)&Device,
> + This->DriverBindingHandle, DeviceHandle,
> + EFI_OPEN_PROTOCOL_BY_DRIVER); if (EFI_ERROR
> + (Status)) {
> + return Status;
> + }
> +
> + //
> + // Restricted to DMA coherent for now // Status = EFI_UNSUPPORTED;
> + if (Device->DmaType != NonDiscoverableDeviceDmaTypeCoherent) {
> + goto CloseProtocol;
> + }
> +
> + for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++)
> {
> + if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices
> [Idx])) {
> + Status = EFI_SUCCESS;
> + break;
> + }
> + }
> +
> + if (EFI_ERROR (Status)) {
> + goto CloseProtocol;
> + }
> +
> + //
> + // We only support MMIO devices, so iterate over the resources to
> + ensure // that they only describe things that we can handle // for
> + (Desc = Device->Resources; Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
> + Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {
> + if (Desc->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR ||
> + Desc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {
> + Status = EFI_UNSUPPORTED;
> + break;
> + }
> + }
> +
> +CloseProtocol:
> + gBS->CloseProtocol (DeviceHandle,
> &gEdkiiNonDiscoverableDeviceProtocolGuid,
> + This->DriverBindingHandle, DeviceHandle);
> +
> + return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonDiscoverablePciDeviceStart (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE DeviceHandle,
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + EFI_STATUS Status;
> +
> + Dev = AllocateZeroPool (sizeof *Dev); if (Dev == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + Status = gBS->OpenProtocol (DeviceHandle,
> + &gEdkiiNonDiscoverableDeviceProtocolGuid,
> + (VOID **)&Dev->Device, This->DriverBindingHandle,
> + DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER); if
> + (EFI_ERROR (Status)) {
> + goto FreeDev;
> + }
> +
> + InitializePciIoProtocol (Dev);
> +
> + //
> + // Setup complete, attempt to export the driver instance's //
> + EFI_PCI_IO_PROTOCOL interface.
> + //
> + Dev->Signature = NON_DISCOVERABLE_PCI_DEVICE_SIG; Status =
> + gBS->InstallProtocolInterface (&DeviceHandle, &gEfiPciIoProtocolGuid,
> + EFI_NATIVE_INTERFACE, &Dev->PciIo); if (EFI_ERROR
> + (Status)) {
> + goto CloseProtocol;
> + }
> +
> + return EFI_SUCCESS;
> +
> +CloseProtocol:
> + gBS->CloseProtocol (DeviceHandle,
> &gEdkiiNonDiscoverableDeviceProtocolGuid,
> + This->DriverBindingHandle, DeviceHandle);
> +
> +FreeDev:
> + FreePool (Dev);
> +
> + return Status;
> +}
> +
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonDiscoverablePciDeviceStop (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE DeviceHandle,
> + IN UINTN NumberOfChildren,
> + IN EFI_HANDLE *ChildHandleBuffer
> + )
> +{
> + EFI_STATUS Status;
> + EFI_PCI_IO_PROTOCOL *PciIo;
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> +
> + Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
> + (VOID **)&PciIo, This->DriverBindingHandle, DeviceHandle,
> + EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (EFI_ERROR
> + (Status)) {
> + return Status;
> + }
> +
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (PciIo);
> +
> + //
> + // Handle Stop() requests for in-use driver instances gracefully.
> + //
> + Status = gBS->UninstallProtocolInterface (DeviceHandle,
> + &gEfiPciIoProtocolGuid, &Dev->PciIo); if (EFI_ERROR
> + (Status)) {
> + return Status;
> + }
> +
> + gBS->CloseProtocol (DeviceHandle,
> &gEdkiiNonDiscoverableDeviceProtocolGuid,
> + This->DriverBindingHandle, DeviceHandle);
> +
> + FreePool (Dev);
> +
> + return EFI_SUCCESS;
> +}
> +
> +
> +//
> +// The static object that groups the Supported() (ie. probe), Start()
> +and // Stop() functions of the driver together. Refer to UEFI Spec
> +2.3.1 + Errata // C, 10.1 EFI Driver Binding Protocol.
> +//
> +STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
> + &NonDiscoverablePciDeviceSupported,
> + &NonDiscoverablePciDeviceStart,
> + &NonDiscoverablePciDeviceStop,
> + 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed
> +drivers
> + NULL,
> + NULL
> +};
> +
> +//
> +// Entry point of this driver.
> +//
> +EFI_STATUS
> +EFIAPI
> +NonDiscoverablePciDeviceDxeEntryPoint (
> + IN EFI_HANDLE ImageHandle,
> + IN EFI_SYSTEM_TABLE *SystemTable
> + )
> +{
> + return EfiLibInstallDriverBindingComponentName2 (
> + ImageHandle,
> + SystemTable,
> + &gDriverBinding,
> + ImageHandle,
> + &gComponentName,
> + &gComponentName2
> + );
> +}
> diff --git
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.inf
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.inf
> new file mode 100644
> index 000000000000..996fe310e0e3
> --- /dev/null
> +++
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> Pc
> +++ iDeviceDxe.inf
> @@ -0,0 +1,52 @@
> +## @file
> +# Copyright (C) 2016, Linaro Ltd.
> +#
> +# 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.
> +#
> +##
> +
> +[Defines]
> + INF_VERSION = 0x00010019
> + BASE_NAME = NonDiscoverablePciDeviceDxe
> + FILE_GUID = 71fd84cd-353b-464d-b7a4-6ea7b96995cb
> + MODULE_TYPE = UEFI_DRIVER
> + VERSION_STRING = 1.0
> + ENTRY_POINT = NonDiscoverablePciDeviceDxeEntryPoint
> +
> +[Sources]
> + ComponentName.c
> + NonDiscoverablePciDeviceDxe.c
> + NonDiscoverablePciDeviceIo.c
> + NonDiscoverablePciDeviceIo.h
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> + BaseMemoryLib
> + DebugLib
> + MemoryAllocationLib
> + UefiBootServicesTableLib
> + UefiDriverEntryPoint
> + UefiLib
> +
> +[Protocols]
> + gEfiPciIoProtocolGuid ## BY_START
> + gEdkiiNonDiscoverableDeviceProtocolGuid ## TO_START
> +
> +[Guids]
> + gEdkiiNonDiscoverableAhciDeviceGuid
> + gEdkiiNonDiscoverableEhciDeviceGuid
> + gEdkiiNonDiscoverableNvmeDeviceGuid
> + gEdkiiNonDiscoverableOhciDeviceGuid
> + gEdkiiNonDiscoverableSdhciDeviceGuid
> + gEdkiiNonDiscoverableUfsDeviceGuid
> + gEdkiiNonDiscoverableUhciDeviceGuid
> + gEdkiiNonDiscoverableXhciDeviceGuid
> diff --git
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.c
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.c
> new file mode 100644
> index 000000000000..fd59267a8d66
> --- /dev/null
> +++
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> Pc
> +++ iDeviceIo.c
> @@ -0,0 +1,797 @@
> +/** @file
> +
> + Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
> + Copyright (c) 2016, Linaro, Ltd. 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
> +
> + 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 "NonDiscoverablePciDeviceIo.h"
> +
> +#include <IndustryStandard/Acpi.h>
> +
> +#include <Protocol/PciRootBridgeIo.h>
> +
> +typedef struct {
> + EFI_PHYSICAL_ADDRESS AllocAddress;
> + VOID *HostAddress;
> + EFI_PCI_IO_PROTOCOL_OPERATION Operation;
> + UINTN NumberOfBytes;
> +} NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO;
> +
> +//
> +// Get the resource associated with BAR number 'BarIndex'.
> +//
> +STATIC
> +EFI_STATUS
> +GetBarResource (
> + IN NON_DISCOVERABLE_PCI_DEVICE *Dev,
> + IN UINT8 BarIndex,
> + OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptor
> + )
> +{
> + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
> +
> + if (BarIndex < Dev->BarOffset) {
> + return EFI_NOT_FOUND;
> + }
> +
> + BarIndex -= Dev->BarOffset;
> +
> + for (Desc = Dev->Device->Resources;
> + Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
> + Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {
> +
> + if (BarIndex == 0) {
> + *Descriptor = Desc;
> + return EFI_SUCCESS;
> + }
> +
> + BarIndex -= 1;
> + }
> + return EFI_NOT_FOUND;
> +}
> +
> +STATIC
> +EFI_STATUS
> +PciIoPollMem (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
> + IN UINT8 BarIndex,
> + IN UINT64 Offset,
> + IN UINT64 Mask,
> + IN UINT64 Value,
> + IN UINT64 Delay,
> + OUT UINT64 *Result
> + )
> +{
> + ASSERT (FALSE);
> + return EFI_UNSUPPORTED;
> +}
> +
> +STATIC
> +EFI_STATUS
> +PciIoPollIo (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
> + IN UINT8 BarIndex,
> + IN UINT64 Offset,
> + IN UINT64 Mask,
> + IN UINT64 Value,
> + IN UINT64 Delay,
> + OUT UINT64 *Result
> + )
> +{
> + ASSERT (FALSE);
> + return EFI_UNSUPPORTED;
> +}
> +
> +STATIC
> +EFI_STATUS
> +PciIoMemRW (
> + IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
> + IN UINTN Count,
> + IN UINTN DstStride,
> + IN VOID *Dst,
> + IN UINTN SrcStride,
> + OUT CONST VOID *Src
> + )
> +{
> + volatile UINT8 *Dst8;
> + volatile UINT16 *Dst16;
> + volatile UINT32 *Dst32;
> + volatile CONST UINT8 *Src8;
> + volatile CONST UINT16 *Src16;
> + volatile CONST UINT32 *Src32;
> +
> + //
> + // Loop for each iteration and move the data // switch (Width &
> + 0x3) { case EfiPciWidthUint8:
> + Dst8 = (UINT8 *)Dst;
> + Src8 = (UINT8 *)Src;
> + for (;Count > 0; Count--, Dst8 += DstStride, Src8 += SrcStride) {
> + *Dst8 = *Src8;
> + }
> + break;
> + case EfiPciWidthUint16:
> + Dst16 = (UINT16 *)Dst;
> + Src16 = (UINT16 *)Src;
> + for (;Count > 0; Count--, Dst16 += DstStride, Src16 += SrcStride) {
> + *Dst16 = *Src16;
> + }
> + break;
> + case EfiPciWidthUint32:
> + Dst32 = (UINT32 *)Dst;
> + Src32 = (UINT32 *)Src;
> + for (;Count > 0; Count--, Dst32 += DstStride, Src32 += SrcStride) {
> + *Dst32 = *Src32;
> + }
> + break;
> + default:
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +PciIoMemRead (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
> + IN UINT8 BarIndex,
> + IN UINT64 Offset,
> + IN UINTN Count,
> + IN OUT VOID *Buffer
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + UINTN AlignMask;
> + VOID *Address;
> + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
> + EFI_STATUS Status;
> +
> + if (Buffer == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
> +
> + //
> + // Only allow accesses to the BARs we emulate // Status =
> + GetBarResource (Dev, BarIndex, &Desc); if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + if (Offset + (Count << (Width & 0x3)) > Desc->AddrLen) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + Address = (VOID *)(UINTN)(Desc->AddrRangeMin + Offset); AlignMask =
> + (1 << (Width & 0x03)) - 1; if ((UINTN)Address & AlignMask) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + switch (Width) {
> + case EfiPciWidthUint8:
> + case EfiPciWidthUint16:
> + case EfiPciWidthUint32:
> + case EfiPciWidthUint64:
> + return PciIoMemRW (Width, Count, 1, Buffer, 1, Address);
> +
> + case EfiPciWidthFifoUint8:
> + case EfiPciWidthFifoUint16:
> + case EfiPciWidthFifoUint32:
> + case EfiPciWidthFifoUint64:
> + return PciIoMemRW (Width, Count, 1, Buffer, 0, Address);
> +
> + case EfiPciWidthFillUint8:
> + case EfiPciWidthFillUint16:
> + case EfiPciWidthFillUint32:
> + case EfiPciWidthFillUint64:
> + return PciIoMemRW (Width, Count, 0, Buffer, 1, Address);
> +
> + default:
> + break;
> + }
> + return EFI_INVALID_PARAMETER;
> +}
> +
> +STATIC
> +EFI_STATUS
> +PciIoMemWrite (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
> + IN UINT8 BarIndex,
> + IN UINT64 Offset,
> + IN UINTN Count,
> + IN OUT VOID *Buffer
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + UINTN AlignMask;
> + VOID *Address;
> + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
> + EFI_STATUS Status;
> +
> + if (Buffer == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
> +
> + //
> + // Only allow accesses to the BARs we emulate // Status =
> + GetBarResource (Dev, BarIndex, &Desc); if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + if (Offset + (Count << (Width & 0x3)) > Desc->AddrLen) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + Address = (VOID *)(UINTN)(Desc->AddrRangeMin + Offset); AlignMask =
> + (1 << (Width & 0x03)) - 1; if ((UINTN)Address & AlignMask) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + switch (Width) {
> + case EfiPciWidthUint8:
> + case EfiPciWidthUint16:
> + case EfiPciWidthUint32:
> + case EfiPciWidthUint64:
> + return PciIoMemRW (Width, Count, 1, Address, 1, Buffer);
> +
> + case EfiPciWidthFifoUint8:
> + case EfiPciWidthFifoUint16:
> + case EfiPciWidthFifoUint32:
> + case EfiPciWidthFifoUint64:
> + return PciIoMemRW (Width, Count, 0, Address, 1, Buffer);
> +
> + case EfiPciWidthFillUint8:
> + case EfiPciWidthFillUint16:
> + case EfiPciWidthFillUint32:
> + case EfiPciWidthFillUint64:
> + return PciIoMemRW (Width, Count, 1, Address, 0, Buffer);
> +
> + default:
> + break;
> + }
> + return EFI_INVALID_PARAMETER;
> +}
> +
> +STATIC
> +EFI_STATUS
> +PciIoIoRead (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
> + IN UINT8 BarIndex,
> + IN UINT64 Offset,
> + IN UINTN Count,
> + IN OUT VOID *Buffer
> + )
> +{
> + ASSERT (FALSE);
> + return EFI_UNSUPPORTED;
> +}
> +
> +STATIC
> +EFI_STATUS
> +PciIoIoWrite (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
> + IN UINT8 BarIndex,
> + IN UINT64 Offset,
> + IN UINTN Count,
> + IN OUT VOID *Buffer
> + )
> +{
> + ASSERT (FALSE);
> + return EFI_UNSUPPORTED;
> +}
> +
> +STATIC
> +EFI_STATUS
> +PciIoPciRead (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
> + IN UINT32 Offset,
> + IN UINTN Count,
> + IN OUT VOID *Buffer
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + VOID *Address;
> + UINTN Length;
> +
> + if (Width < 0 || Width >= EfiPciIoWidthMaximum || Buffer == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
> + Address = (UINT8 *)&Dev->ConfigSpace + Offset; Length = Count <<
> + ((UINTN)Width & 0x3);
> +
> + if (Offset + Length > sizeof (Dev->ConfigSpace)) {
> + //
> + // Read all zeroes for config space accesses beyond the first
> + // 64 bytes
> + //
> + Length -= sizeof (Dev->ConfigSpace) - Offset;
> + ZeroMem ((UINT8 *)Buffer + sizeof (Dev->ConfigSpace) - Offset,
> + Length);
> +
> + Count -= Length >> ((UINTN)Width & 0x3);
> + }
> + return PciIoMemRW (Width, Count, 1, Buffer, 1, Address); }
> +
> +STATIC
> +EFI_STATUS
> +PciIoPciWrite (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
> + IN UINT32 Offset,
> + IN UINTN Count,
> + IN OUT VOID *Buffer
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + VOID *Address;
> +
> + if (Width < 0 || Width >= EfiPciIoWidthMaximum || Buffer == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
> + Address = (UINT8 *)&Dev->ConfigSpace + Offset;
> +
> + if (Offset + (Count << ((UINTN)Width & 0x3)) > sizeof (Dev->ConfigSpace))
> {
> + return EFI_UNSUPPORTED;
> + }
> +
> + return PciIoMemRW (Width, Count, 1, Address, 1, Buffer); }
> +
> +STATIC
> +EFI_STATUS
> +PciIoCopyMem (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
> + IN UINT8 DestBarIndex,
> + IN UINT64 DestOffset,
> + IN UINT8 SrcBarIndex,
> + IN UINT64 SrcOffset,
> + IN UINTN Count
> + )
> +{
> + ASSERT (FALSE);
> + return EFI_UNSUPPORTED;
> +}
> +
> +STATIC
> +EFI_STATUS
> +CoherentPciIoMap (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
> + IN VOID *HostAddress,
> + IN OUT UINTN *NumberOfBytes,
> + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
> + OUT VOID **Mapping
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + EFI_STATUS Status;
> + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;
> +
> + //
> + // If HostAddress exceeds 4 GB, and this device does not support
> + 64-bit DMA // addressing, we need to allocate a bounce buffer and copy
> over the data.
> + //
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
> + if ((Dev->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) ==
> 0 &&
> + (UINTN)HostAddress + *NumberOfBytes > SIZE_4GB) {
> +
> + //
> + // Bounce buffering is not possible for consistent mappings
> + //
> + if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + MapInfo = AllocatePool (sizeof *MapInfo);
> + if (MapInfo == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + MapInfo->AllocAddress = MAX_UINT32;
> + MapInfo->HostAddress = HostAddress;
> + MapInfo->Operation = Operation;
> + MapInfo->NumberOfBytes = *NumberOfBytes;
> +
> + Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData,
> + EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),
> + &MapInfo->AllocAddress);
> + if (EFI_ERROR (Status)) {
> + //
> + // If we fail here, it is likely because the system has no memory below
> + // 4 GB to begin with. There is not much we can do about that other than
> + // fail the map request.
> + //
> + FreePool (MapInfo);
> + return EFI_DEVICE_ERROR;
> + }
> + if (Operation == EfiPciIoOperationBusMasterRead) {
> + gBS->CopyMem ((VOID *)(UINTN)MapInfo->AllocAddress, HostAddress,
> + *NumberOfBytes);
> + }
> + *DeviceAddress = MapInfo->AllocAddress;
> + *Mapping = MapInfo;
> + } else {
> + *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
> + *Mapping = NULL;
> + }
> + return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +CoherentPciIoUnmap (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN VOID *Mapping
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;
> +
> + MapInfo = Mapping;
> + if (MapInfo != NULL) {
> + if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {
> + gBS->CopyMem (MapInfo->HostAddress, (VOID *)(UINTN)MapInfo-
> >AllocAddress,
> + MapInfo->NumberOfBytes);
> + }
> + gBS->FreePages (MapInfo->AllocAddress,
> + EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes));
> + FreePool (MapInfo);
> + }
> + return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +CoherentPciIoAllocateBuffer (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_ALLOCATE_TYPE Type,
> + IN EFI_MEMORY_TYPE MemoryType,
> + IN UINTN Pages,
> + OUT VOID **HostAddress,
> + IN UINT64 Attributes
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + EFI_PHYSICAL_ADDRESS AllocAddress;
> + EFI_ALLOCATE_TYPE AllocType;
> + EFI_STATUS Status;
> +
> + if ((Attributes & ~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE |
> + EFI_PCI_ATTRIBUTE_MEMORY_CACHED)) != 0) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + //
> + // Allocate below 4 GB if the dual address cycle attribute has not
> + // been set. If the system has no memory available below 4 GB, there
> + // is little we can do except propagate the error.
> + //
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
> + if ((Dev->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) ==
> 0) {
> + AllocAddress = MAX_UINT32;
> + AllocType = AllocateMaxAddress;
> + } else {
> + AllocType = AllocateAnyPages;
> + }
> +
> + Status = gBS->AllocatePages (AllocType, MemoryType, Pages,
> +&AllocAddress);
> + if (!EFI_ERROR (Status)) {
> + *HostAddress = (VOID *)(UINTN)AllocAddress;
> + }
> + return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +CoherentPciIoFreeBuffer (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN UINTN Pages,
> + IN VOID *HostAddress
> + )
> +{
> + FreePages (HostAddress, Pages);
> + return EFI_SUCCESS;
> +}
> +
> +
> +STATIC
> +EFI_STATUS
> +PciIoFlush (
> + IN EFI_PCI_IO_PROTOCOL *This
> + )
> +{
> + return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +PciIoGetLocation (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + OUT UINTN *SegmentNumber,
> + OUT UINTN *BusNumber,
> + OUT UINTN *DeviceNumber,
> + OUT UINTN *FunctionNumber
> + )
> +{
> + if (SegmentNumber == NULL ||
> + BusNumber == NULL ||
> + DeviceNumber == NULL ||
> + FunctionNumber == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + *SegmentNumber = 0;
> + *BusNumber = 0xff;
> + *DeviceNumber = 0;
> + *FunctionNumber = 0;
> +
> + return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +PciIoAttributes (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
> + IN UINT64 Attributes,
> + OUT UINT64 *Result OPTIONAL
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + BOOLEAN Enable;
> +
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
> +
> + Enable = FALSE;
> + switch (Operation) {
> + case EfiPciIoAttributeOperationGet:
> + if (Result == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> + *Result = Dev->Attributes;
> + break;
> +
> + case EfiPciIoAttributeOperationSupported:
> + if (Result == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> + *Result = EFI_PCI_DEVICE_ENABLE |
> EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
> + break;
> +
> + case EfiPciIoAttributeOperationEnable:
> + Attributes |= Dev->Attributes;
> + case EfiPciIoAttributeOperationSet:
> + Enable = ((~Dev->Attributes & Attributes) & EFI_PCI_DEVICE_ENABLE) !=
> 0;
> + Dev->Attributes = Attributes;
> + break;
> +
> + case EfiPciIoAttributeOperationDisable:
> + Dev->Attributes &= ~Attributes;
> + break;
> +
> + default:
> + return EFI_INVALID_PARAMETER;
> + };
> +
> + //
> + // If we're setting any of the EFI_PCI_DEVICE_ENABLE bits, perform
> + // the device specific initialization now.
> + //
> + if (Enable && !Dev->Enabled && Dev->Device->Initialize != NULL) {
> + Dev->Device->Initialize (Dev->Device);
> + Dev->Enabled = TRUE;
> + }
> + return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +PciIoGetBarAttributes (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN UINT8 BarIndex,
> + OUT UINT64 *Supports OPTIONAL,
> + OUT VOID **Resources OPTIONAL
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor, *BarDesc;
> + EFI_ACPI_END_TAG_DESCRIPTOR *End;
> + EFI_STATUS Status;
> +
> + if (Supports == NULL && Resources == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
> +
> + Status = GetBarResource (Dev, BarIndex, &BarDesc); if (EFI_ERROR
> + (Status)) {
> + return Status;
> + }
> +
> + //
> + // Don't expose any configurable attributes for our emulated BAR //
> + if (Supports != NULL) {
> + *Supports = 0;
> + }
> +
> + if (Resources != NULL) {
> + Descriptor = AllocatePool (sizeof
> (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
> + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
> + if (Descriptor == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + CopyMem (Descriptor, BarDesc, sizeof *Descriptor);
> +
> + End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);
> + End->Desc = ACPI_END_TAG_DESCRIPTOR;
> + End->Checksum = 0;
> +
> + *Resources = Descriptor;
> + }
> + return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +PciIoSetBarAttributes (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN UINT64 Attributes,
> + IN UINT8 BarIndex,
> + IN OUT UINT64 *Offset,
> + IN OUT UINT64 *Length
> + )
> +{
> + ASSERT (FALSE);
> + return EFI_UNSUPPORTED;
> +}
> +
> +STATIC CONST EFI_PCI_IO_PROTOCOL PciIoTemplate = {
> + PciIoPollMem,
> + PciIoPollIo,
> + { PciIoMemRead, PciIoMemWrite },
> + { PciIoIoRead, PciIoIoWrite },
> + { PciIoPciRead, PciIoPciWrite },
> + PciIoCopyMem,
> + CoherentPciIoMap,
> + CoherentPciIoUnmap,
> + CoherentPciIoAllocateBuffer,
> + CoherentPciIoFreeBuffer,
> + PciIoFlush,
> + PciIoGetLocation,
> + PciIoAttributes,
> + PciIoGetBarAttributes,
> + PciIoSetBarAttributes,
> + 0,
> + 0
> +};
> +
> +VOID
> +InitializePciIoProtocol (
> + NON_DISCOVERABLE_PCI_DEVICE *Dev
> + )
> +{
> + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
> + INTN Idx;
> +
> + InitializeListHead (&Dev->UncachedAllocationList);
> +
> + Dev->ConfigSpace.Hdr.VendorId = PCI_ID_VENDOR_UNKNOWN;
> + Dev->ConfigSpace.Hdr.DeviceId = PCI_ID_DEVICE_DONTCARE;
> +
> + // Copy protocol structure
> + CopyMem(&Dev->PciIo, &PciIoTemplate, sizeof PciIoTemplate);
> +
> + if (CompareGuid (Dev->Device->Type,
> &gEdkiiNonDiscoverableAhciDeviceGuid)) {
> + Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_MASS_STORAGE_AHCI;
> + Dev->ConfigSpace.Hdr.ClassCode[1] =
> PCI_CLASS_MASS_STORAGE_SATADPA;
> + Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_MASS_STORAGE;
> + Dev->BarOffset = 5;
> + } else if (CompareGuid (Dev->Device->Type,
> + &gEdkiiNonDiscoverableEhciDeviceGuid)) {
> + Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_EHCI;
> + Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;
> + Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;
> + Dev->BarOffset = 0;
> + } else if (CompareGuid (Dev->Device->Type,
> + &gEdkiiNonDiscoverableNvmeDeviceGuid)) {
> + Dev->ConfigSpace.Hdr.ClassCode[0] = 0x2; // PCI_IF_NVMHCI
> + Dev->ConfigSpace.Hdr.ClassCode[1] = 0x8; //
> PCI_CLASS_MASS_STORAGE_NVM
> + Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_MASS_STORAGE;
> + Dev->BarOffset = 0;
> + } else if (CompareGuid (Dev->Device->Type,
> + &gEdkiiNonDiscoverableOhciDeviceGuid)) {
> + Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_OHCI;
> + Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;
> + Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;
> + Dev->BarOffset = 0;
> + } else if (CompareGuid (Dev->Device->Type,
> + &gEdkiiNonDiscoverableSdhciDeviceGuid)) {
> + Dev->ConfigSpace.Hdr.ClassCode[0] = 0x0; // don't care
> + Dev->ConfigSpace.Hdr.ClassCode[1] =
> PCI_SUBCLASS_SD_HOST_CONTROLLER;
> + Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SYSTEM_PERIPHERAL;
> + Dev->BarOffset = 0;
> + } else if (CompareGuid (Dev->Device->Type,
> + &gEdkiiNonDiscoverableXhciDeviceGuid)) {
> + Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_XHCI;
> + Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;
> + Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;
> + Dev->BarOffset = 0;
> + } else if (CompareGuid (Dev->Device->Type,
> + &gEdkiiNonDiscoverableUhciDeviceGuid)) {
> + Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_UHCI;
> + Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;
> + Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;
> + Dev->BarOffset = 0;
> + } else if (CompareGuid (Dev->Device->Type,
> + &gEdkiiNonDiscoverableUfsDeviceGuid)) {
> + Dev->ConfigSpace.Hdr.ClassCode[0] = 0x0; // don't care
> + Dev->ConfigSpace.Hdr.ClassCode[1] = 0x9; // UFS controller subclass;
> + Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_MASS_STORAGE;
> + Dev->BarOffset = 0;
> + } else {
> + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); }
> +
> + //
> + // Iterate over the resources to populate the virtual BARs // Idx =
> + Dev->BarOffset; for (Desc = Dev->Device->Resources, Dev->BarCount =
> + 0;
> + Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
> + Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {
> +
> + ASSERT (Desc->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR);
> + ASSERT (Desc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM);
> +
> + if (Idx >= PCI_MAX_BARS ||
> + (Idx == PCI_MAX_BARS - 1 && Desc->AddrSpaceGranularity == 64)) {
> + DEBUG ((DEBUG_ERROR,
> + "%a: resource count exceeds number of emulated BARs\n",
> + __FUNCTION__));
> + ASSERT (FALSE);
> + break;
> + }
> +
> + Dev->ConfigSpace.Device.Bar[Idx] = (UINT32)Desc->AddrRangeMin;
> + Dev->BarCount++;
> +
> + if (Desc->AddrSpaceGranularity == 64) {
> + Dev->ConfigSpace.Device.Bar[Idx] |= 0x4;
> + Dev->ConfigSpace.Device.Bar[++Idx] = (UINT32)(Desc-
> >AddrRangeMin >> 32);
1. You need to use RShiftU64 otherwise the above code will break the
build process in 32bit.
> + }
> + }
> +}
> diff --git
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.h
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.h
> new file mode 100644
> index 000000000000..bc0a3d3258f9
> --- /dev/null
> +++
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> Pc
> +++ iDeviceIo.h
> @@ -0,0 +1,84 @@
> +/** @file
> +
> + Copyright (C) 2016, Linaro Ltd. 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
> +
> + 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 __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
> +#define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h> #include
> +<Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +
> +#include <IndustryStandard/Pci.h>
> +
> +#include <Protocol/ComponentName.h>
> +#include <Protocol/NonDiscoverableDevice.h>
> +#include <Protocol/PciIo.h>
> +
> +#define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I',
> +'D')
> +
> +#define NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(PciIoPointer) \
> + CR (PciIoPointer, NON_DISCOVERABLE_PCI_DEVICE, PciIo, \
> + NON_DISCOVERABLE_PCI_DEVICE_SIG)
> +
> +#define PCI_ID_VENDOR_UNKNOWN 0xffff
> +#define PCI_ID_DEVICE_DONTCARE 0x0000
> +
> +#define PCI_MAX_BARS 6
> +
> +typedef struct {
> + UINT32 Signature;
> + //
> + // The bound non-discoverable device protocol instance
> + //
> + NON_DISCOVERABLE_DEVICE *Device;
> + //
> + // The exposed PCI I/O protocol instance.
> + //
> + EFI_PCI_IO_PROTOCOL PciIo;
> + //
> + // The emulated PCI config space of the device. Only the minimally
> +required
> + // items are assigned.
> + //
> + PCI_TYPE00 ConfigSpace;
> + //
> + // The first virtual BAR to assign based on the resources described
> + // by the non-discoverable device.
> + //
> + UINT32 BarOffset;
> + //
> + // The number of virtual BARs we expose based on the number of
> + // resources
> + //
> + UINT32 BarCount;
> + //
> + // The PCI I/O attributes for this device
> + //
> + UINT64 Attributes;
> + //
> + // Whether this device has been enabled
> + //
> + BOOLEAN Enabled;
> +} NON_DISCOVERABLE_PCI_DEVICE;
> +
> +VOID
> +InitializePciIoProtocol (
> + NON_DISCOVERABLE_PCI_DEVICE *Device
> + );
> +
> +extern EFI_COMPONENT_NAME_PROTOCOL gComponentName; extern
> +EFI_COMPONENT_NAME2_PROTOCOL gComponentName2;
> +
> +#endif
> diff --git a/MdeModulePkg/MdeModulePkg.dsc
> b/MdeModulePkg/MdeModulePkg.dsc index 20e5e8c78be0..5dd30556cb3c
> 100644
> --- a/MdeModulePkg/MdeModulePkg.dsc
> +++ b/MdeModulePkg/MdeModulePkg.dsc
> @@ -265,6 +265,7 @@ [Components]
> MdeModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf
> MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
> MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
> +
> +
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
> Dev
> + iceDxe.inf
>
> MdeModulePkg/Core/Dxe/DxeMain.inf {
> <LibraryClasses>
> --
> 2.7.4
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4 1/5] MdeModulePkg: introduce non-discoverable device protocol
2016-11-25 15:42 ` [PATCH v4 1/5] MdeModulePkg: introduce non-discoverable device protocol Ard Biesheuvel
@ 2016-11-28 1:57 ` Ni, Ruiyu
0 siblings, 0 replies; 19+ messages in thread
From: Ni, Ruiyu @ 2016-11-28 1:57 UTC (permalink / raw)
To: Ard Biesheuvel, edk2-devel@lists.01.org, leif.lindholm@linaro.org,
Gao, Liming, afish@apple.com, Kinney, Michael D, mw@semihalf.com,
Tian, Feng
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
Thanks/Ray
> -----Original Message-----
> From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
> Sent: Friday, November 25, 2016 11:42 PM
> To: edk2-devel@lists.01.org; leif.lindholm@linaro.org; Gao, Liming
> <liming.gao@intel.com>; afish@apple.com; Ni, Ruiyu <ruiyu.ni@intel.com>;
> Kinney, Michael D <michael.d.kinney@intel.com>; mw@semihalf.com; Tian,
> Feng <feng.tian@intel.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Subject: [PATCH v4 1/5] MdeModulePkg: introduce non-discoverable device
> protocol
>
> Introduce a protocol that can be exposed by a platform for devices that are
> not discoverable, usually because they are wired straight to the memory bus
> rather than to an enumerable bus like PCI or USB.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> MdeModulePkg/Include/Guid/NonDiscoverableDevice.h | 58
> +++++++++++++++
> MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 77
> ++++++++++++++++++++
> MdeModulePkg/MdeModulePkg.dec | 14 ++++
> 3 files changed, 149 insertions(+)
>
> diff --git a/MdeModulePkg/Include/Guid/NonDiscoverableDevice.h
> b/MdeModulePkg/Include/Guid/NonDiscoverableDevice.h
> new file mode 100644
> index 000000000000..d182e4b9d2fe
> --- /dev/null
> +++ b/MdeModulePkg/Include/Guid/NonDiscoverableDevice.h
> @@ -0,0 +1,58 @@
> +/** @file
> + GUIDs to identify devices that are not on a discoverable bus but can
> +be
> + controlled by a standard class driver
> +
> + Copyright (c) 2016, Linaro, Ltd. 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
> +
> + 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 __NON_DISCOVERABLE_DEVICE_GUID_H__
> +#define __NON_DISCOVERABLE_DEVICE_GUID_H__
> +
> +#define EDKII_NON_DISCOVERABLE_AHCI_DEVICE_GUID \
> + { 0xC7D35798, 0xE4D2, 0x4A93, {0xB1, 0x45, 0x54, 0x88, 0x9F, 0x02,
> +0x58, 0x4B } }
> +
> +#define EDKII_NON_DISCOVERABLE_AMBA_DEVICE_GUID \
> + { 0x94440339, 0xCC93, 0x4506, {0xB4, 0xC6, 0xEE, 0x8D, 0x0F, 0x4C,
> +0xA1, 0x91 } }
> +
> +#define EDKII_NON_DISCOVERABLE_EHCI_DEVICE_GUID \
> + { 0xEAEE5615, 0x0CFD, 0x45FC, {0x87, 0x69, 0xA0, 0xD8, 0x56, 0x95,
> +0xAF, 0x85 } }
> +
> +#define EDKII_NON_DISCOVERABLE_NVME_DEVICE_GUID \
> + { 0xC5F25542, 0x2A79, 0x4A26, {0x81, 0xBB, 0x4E, 0xA6, 0x32, 0x33,
> +0xB3, 0x09 } }
> +
> +#define EDKII_NON_DISCOVERABLE_OHCI_DEVICE_GUID \
> + { 0xB20005B0, 0xBB2D, 0x496F, {0x86, 0x9C, 0x23, 0x0B, 0x44, 0x79,
> +0xE7, 0xD1 } }
> +
> +#define EDKII_NON_DISCOVERABLE_SDHCI_DEVICE_GUID \
> + { 0x1DD1D619, 0xF9B8, 0x463E, {0x86, 0x81, 0xD1, 0xDC, 0x7C, 0x07,
> +0xB7, 0x2C } }
> +
> +#define EDKII_NON_DISCOVERABLE_UFS_DEVICE_GUID \
> + { 0x2EA77912, 0x80A8, 0x4947, {0xBE, 0x69, 0xCD, 0xD0, 0x0A, 0xFB,
> +0xE5, 0x56 } }
> +
> +#define EDKII_NON_DISCOVERABLE_UHCI_DEVICE_GUID \
> + { 0xA8CDA0A2, 0x4F37, 0x4A1B, {0x8E, 0x10, 0x8E, 0xF3, 0xCC, 0x3B,
> +0xF3, 0xA8 } }
> +
> +#define EDKII_NON_DISCOVERABLE_XHCI_DEVICE_GUID \
> + { 0xB1BE0BC5, 0x6C28, 0x442D, {0xAA, 0x37, 0x15, 0x1B, 0x42, 0x57,
> +0xBD, 0x78 } }
> +
> +
> +extern EFI_GUID gEdkiiNonDiscoverableAhciDeviceGuid;
> +extern EFI_GUID gEdkiiNonDiscoverableAmbaDeviceGuid;
> +extern EFI_GUID gEdkiiNonDiscoverableEhciDeviceGuid;
> +extern EFI_GUID gEdkiiNonDiscoverableNvmeDeviceGuid;
> +extern EFI_GUID gEdkiiNonDiscoverableOhciDeviceGuid;
> +extern EFI_GUID gEdkiiNonDiscoverableSdhciDeviceGuid;
> +extern EFI_GUID gEdkiiNonDiscoverableUfsDeviceGuid;
> +extern EFI_GUID gEdkiiNonDiscoverableUhciDeviceGuid;
> +extern EFI_GUID gEdkiiNonDiscoverableXhciDeviceGuid;
> +
> +#endif
> diff --git a/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
> b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
> new file mode 100644
> index 000000000000..976ae8387376
> --- /dev/null
> +++ b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
> @@ -0,0 +1,77 @@
> +/** @file
> + Protocol to describe devices that are not on a discoverable bus
> +
> + Copyright (c) 2016, Linaro, Ltd. 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
> +
> + 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 __NON_DISCOVERABLE_DEVICE_H__
> +#define __NON_DISCOVERABLE_DEVICE_H__
> +
> +#include <IndustryStandard/Acpi.h>
> +
> +#define EDKII_NON_DISCOVERABLE_DEVICE_PROTOCOL_GUID \
> + { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 0x8d,
> +0x51, 0x4a } }
> +
> +//
> +// Protocol interface structure
> +//
> +typedef struct _NON_DISCOVERABLE_DEVICE
> NON_DISCOVERABLE_DEVICE;
> +
> +//
> +// Data Types
> +//
> +typedef enum {
> + NonDiscoverableDeviceDmaTypeCoherent,
> + NonDiscoverableDeviceDmaTypeNonCoherent,
> + NonDiscoverableDeviceDmaTypeMax,
> +} NON_DISCOVERABLE_DEVICE_DMA_TYPE;
> +
> +//
> +// Function Prototypes
> +//
> +
> +/**
> + Perform device specific initialization before the device is started
> +
> + @param This The non-discoverable device protocol pointer
> +
> + @retval EFI_SUCCESS Initialization successful, the device may be used
> + @retval Other Initialization failed, device should not be started
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *NON_DISCOVERABLE_DEVICE_INIT) (
> + IN NON_DISCOVERABLE_DEVICE *This
> + );
> +
> +struct _NON_DISCOVERABLE_DEVICE {
> + //
> + // The type of device
> + //
> + CONST EFI_GUID *Type;
> + //
> + // Whether this device is DMA coherent
> + //
> + NON_DISCOVERABLE_DEVICE_DMA_TYPE DmaType;
> + //
> + // Initialization function for the device
> + //
> + NON_DISCOVERABLE_DEVICE_INIT Initialize;
> + //
> + // The MMIO and I/O regions owned by the device
> + //
> + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources;
> +};
> +
> +extern EFI_GUID gEdkiiNonDiscoverableDeviceProtocolGuid;
> +
> +#endif
> diff --git a/MdeModulePkg/MdeModulePkg.dec
> b/MdeModulePkg/MdeModulePkg.dec index 22898e3f7487..588f5e97dbc2
> 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -362,6 +362,17 @@ [Guids]
> ## Include/Guid/PiSmmMemoryAttributesTable.h
> gEdkiiPiSmmMemoryAttributesTableGuid = { 0x6b9fd3f7, 0x16df, 0x45e8,
> {0xbd, 0x39, 0xb9, 0x4a, 0x66, 0x54, 0x1a, 0x5d}}
>
> + ## Include/Guid/NonDiscoverableDevice.h
> + gEdkiiNonDiscoverableAhciDeviceGuid = { 0xC7D35798, 0xE4D2, 0x4A93,
> + {0xB1, 0x45, 0x54, 0x88, 0x9F, 0x02, 0x58, 0x4B } }
> + gEdkiiNonDiscoverableAmbaDeviceGuid = { 0x94440339, 0xCC93, 0x4506,
> + {0xB4, 0xC6, 0xEE, 0x8D, 0x0F, 0x4C, 0xA1, 0x91 } }
> + gEdkiiNonDiscoverableEhciDeviceGuid = { 0xEAEE5615, 0x0CFD, 0x45FC,
> + {0x87, 0x69, 0xA0, 0xD8, 0x56, 0x95, 0xAF, 0x85 } }
> + gEdkiiNonDiscoverableNvmeDeviceGuid = { 0xC5F25542, 0x2A79, 0x4A26,
> + {0x81, 0xBB, 0x4E, 0xA6, 0x32, 0x33, 0xB3, 0x09 } }
> + gEdkiiNonDiscoverableOhciDeviceGuid = { 0xB20005B0, 0xBB2D, 0x496F,
> + {0x86, 0x9C, 0x23, 0x0B, 0x44, 0x79, 0xE7, 0xD1 } }
> + gEdkiiNonDiscoverableSdhciDeviceGuid = { 0x1DD1D619, 0xF9B8, 0x463E,
> + {0x86, 0x81, 0xD1, 0xDC, 0x7C, 0x07, 0xB7, 0x2C } }
> + gEdkiiNonDiscoverableUfsDeviceGuid = { 0x2EA77912, 0x80A8, 0x4947,
> + {0xBE, 0x69, 0xCD, 0xD0, 0x0A, 0xFB, 0xE5, 0x56 } }
> + gEdkiiNonDiscoverableUhciDeviceGuid = { 0xA8CDA0A2, 0x4F37, 0x4A1B,
> + {0x8E, 0x10, 0x8E, 0xF3, 0xCC, 0x3B, 0xF3, 0xA8 } }
> + gEdkiiNonDiscoverableXhciDeviceGuid = { 0xB1BE0BC5, 0x6C28, 0x442D,
> + {0xAA, 0x37, 0x15, 0x1B, 0x42, 0x57, 0xBD, 0x78 } }
> +
> [Ppis]
> ## Include/Ppi/AtaController.h
> gPeiAtaControllerPpiGuid = { 0xa45e60d1, 0xc719, 0x44aa, { 0xb0, 0x7a,
> 0xaa, 0x77, 0x7f, 0x85, 0x90, 0x6d }}
> @@ -512,6 +523,9 @@ [Protocols]
> # Include/Protocol/Ps2Policy.h
> gEfiPs2PolicyProtocolGuid = { 0x4DF19259, 0xDC71, 0x4D46, { 0xBE, 0xF1,
> 0x35, 0x7B, 0xB5, 0x78, 0xC4, 0x18 } }
>
> + ## Include/Protocol/NonDiscoverableDevice.h
> + gEdkiiNonDiscoverableDeviceProtocolGuid = { 0x0d51905b, 0xb77e,
> + 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 0x8d, 0x51, 0x4a } }
> +
> #
> # [Error.gEfiMdeModulePkgTokenSpaceGuid]
> # 0x80000001 | Invalid value provided.
> --
> 2.7.4
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4 2/5] MdeModulePkg: introduce helper library to register non-discoverable devices
2016-11-25 15:42 ` [PATCH v4 2/5] MdeModulePkg: introduce helper library to register non-discoverable devices Ard Biesheuvel
@ 2016-11-28 1:58 ` Ni, Ruiyu
0 siblings, 0 replies; 19+ messages in thread
From: Ni, Ruiyu @ 2016-11-28 1:58 UTC (permalink / raw)
To: Ard Biesheuvel, edk2-devel@lists.01.org, leif.lindholm@linaro.org,
Gao, Liming, afish@apple.com, Kinney, Michael D, mw@semihalf.com,
Tian, Feng
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
Thanks/Ray
> -----Original Message-----
> From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
> Sent: Friday, November 25, 2016 11:42 PM
> To: edk2-devel@lists.01.org; leif.lindholm@linaro.org; Gao, Liming
> <liming.gao@intel.com>; afish@apple.com; Ni, Ruiyu <ruiyu.ni@intel.com>;
> Kinney, Michael D <michael.d.kinney@intel.com>; mw@semihalf.com; Tian,
> Feng <feng.tian@intel.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Subject: [PATCH v4 2/5] MdeModulePkg: introduce helper library to register
> non-discoverable devices
>
> Non-discoverable devices need to be registered explicitly by the platform.
> Introduce a helper library that takes care of this.
>
> This implementation currently only supports registering devices that are
> covered by one or more MMIO resources. The underlying protocol allows for
> more flexibility than that, but this is currently sufficient for the use cases that
> we know about.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h
> | 62 ++++++
>
> MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscove
> rableDeviceRegistrationLib.c | 204 ++++++++++++++++++++
>
> MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscove
> rableDeviceRegistrationLib.inf | 46 +++++
> MdeModulePkg/MdeModulePkg.dec | 4
> +
> MdeModulePkg/MdeModulePkg.dsc | 2
> +
> 5 files changed, 318 insertions(+)
>
> diff --git
> a/MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h
> b/MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h
> new file mode 100644
> index 000000000000..120d91466095
> --- /dev/null
> +++
> b/MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.
> +++ h
> @@ -0,0 +1,62 @@
> +/** @file
> + Copyright (c) 2016, Linaro, Ltd. 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
> +
> + 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 __NON_DISCOVERABLE_DEVICE_REGISTRATION_LIB_H__
> +#define __NON_DISCOVERABLE_DEVICE_REGISTRATION_LIB_H__
> +
> +#include <Protocol/NonDiscoverableDevice.h>
> +
> +typedef enum {
> + NonDiscoverableDeviceTypeAhci,
> + NonDiscoverableDeviceTypeAmba,
> + NonDiscoverableDeviceTypeEhci,
> + NonDiscoverableDeviceTypeNvme,
> + NonDiscoverableDeviceTypeOhci,
> + NonDiscoverableDeviceTypeSdhci,
> + NonDiscoverableDeviceTypeUfs,
> + NonDiscoverableDeviceTypeUhci,
> + NonDiscoverableDeviceTypeXhci,
> + NonDiscoverableDeviceTypeMax,
> +} NON_DISCOVERABLE_DEVICE_TYPE;
> +
> +/**
> + Register a non-discoverable MMIO device
> +
> + @param[in] DeviceType The type of non-discoverable device
> + @param[in] DmaType Whether the device is DMA coherent
> + @param[in] InitFunc Initialization routine to be invoked when
> + the device is enabled
> + @param[in,out] Handle The handle onto which to install the
> + non-discoverable device protocol.
> + If Handle is NULL or *Handle is NULL, a
> + new handle will be allocated.
> + @param[in] NumMmioResources The number of UINTN base/size
> pairs that
> + follow, each describing an MMIO region
> + owned by the device
> +
> + @retval EFI_SUCCESS The registration succeeded.
> + @retval Other The registration failed.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RegisterNonDiscoverableMmioDevice (
> + IN NON_DISCOVERABLE_DEVICE_TYPE Type,
> + IN NON_DISCOVERABLE_DEVICE_DMA_TYPE DmaType,
> + IN NON_DISCOVERABLE_DEVICE_INIT InitFunc,
> + IN OUT EFI_HANDLE *Handle OPTIONAL,
> + IN UINTN NumMmioResources,
> + ...
> + );
> +
> +#endif
> diff --git
> a/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDisco
> verableDeviceRegistrationLib.c
> b/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDisco
> verableDeviceRegistrationLib.c
> new file mode 100644
> index 000000000000..94cd946b69d3
> --- /dev/null
> +++
> b/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDisco
> +++ verableDeviceRegistrationLib.c
> @@ -0,0 +1,204 @@
> +/** @file
> + Copyright (c) 2016, Linaro, Ltd. 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
> +
> + 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 <PiDxe.h>
> +
> +#include <Guid/NonDiscoverableDevice.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/MemoryAllocationLib.h> #include
> +<Library/NonDiscoverableDeviceRegistrationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <Protocol/DevicePath.h>
> +#include <Protocol/NonDiscoverableDevice.h>
> +
> +STATIC
> +CONST EFI_GUID *
> +GetGuidFromType (
> + IN NON_DISCOVERABLE_DEVICE_TYPE Type
> + )
> +{
> + switch (Type) {
> + case NonDiscoverableDeviceTypeAhci:
> + return &gEdkiiNonDiscoverableAhciDeviceGuid;
> +
> + case NonDiscoverableDeviceTypeAmba:
> + return &gEdkiiNonDiscoverableAmbaDeviceGuid;
> +
> + case NonDiscoverableDeviceTypeEhci:
> + return &gEdkiiNonDiscoverableEhciDeviceGuid;
> +
> + case NonDiscoverableDeviceTypeNvme:
> + return &gEdkiiNonDiscoverableNvmeDeviceGuid;
> +
> + case NonDiscoverableDeviceTypeOhci:
> + return &gEdkiiNonDiscoverableOhciDeviceGuid;
> +
> + case NonDiscoverableDeviceTypeSdhci:
> + return &gEdkiiNonDiscoverableSdhciDeviceGuid;
> +
> + case NonDiscoverableDeviceTypeUfs:
> + return &gEdkiiNonDiscoverableUfsDeviceGuid;
> +
> + case NonDiscoverableDeviceTypeUhci:
> + return &gEdkiiNonDiscoverableUhciDeviceGuid;
> +
> + case NonDiscoverableDeviceTypeXhci:
> + return &gEdkiiNonDiscoverableXhciDeviceGuid;
> +
> + default:
> + return NULL;
> + }
> +}
> +
> +#pragma pack (1)
> +typedef struct {
> + VENDOR_DEVICE_PATH Vendor;
> + UINT64 BaseAddress;
> + UINT8 ResourceType;
> + EFI_DEVICE_PATH_PROTOCOL End;
> +} NON_DISCOVERABLE_DEVICE_PATH;
> +#pragma pack ()
> +
> +/**
> + Register a non-discoverable MMIO device
> +
> + @param[in] DeviceType The type of non-discoverable device
> + @param[in] DmaType Whether the device is DMA coherent
> + @param[in] InitFunc Initialization routine to be invoked when
> + the device is enabled
> + @param[in,out] Handle The handle onto which to install the
> + non-discoverable device protocol.
> + If Handle is NULL or *Handle is NULL, a
> + new handle will be allocated.
> + @param[in] NumMmioResources The number of UINTN base/size
> pairs that
> + follow, each describing an MMIO region
> + owned by the device
> +
> + @retval EFI_SUCCESS The registration succeeded.
> + @retval EFI_INVALID_PARAMETER An invalid argument was given
> + @retval Other The registration failed.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RegisterNonDiscoverableMmioDevice (
> + IN NON_DISCOVERABLE_DEVICE_TYPE Type,
> + IN NON_DISCOVERABLE_DEVICE_DMA_TYPE DmaType,
> + IN NON_DISCOVERABLE_DEVICE_INIT InitFunc,
> + IN OUT EFI_HANDLE *Handle OPTIONAL,
> + IN UINTN NumMmioResources,
> + ...
> + )
> +{
> + NON_DISCOVERABLE_DEVICE *Device;
> + NON_DISCOVERABLE_DEVICE_PATH *DevicePath;
> + EFI_HANDLE LocalHandle;
> + EFI_STATUS Status;
> + UINTN AllocSize;
> + UINTN Index;
> + VA_LIST Args;
> + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
> + EFI_ACPI_END_TAG_DESCRIPTOR *End;
> + UINTN Base, Size;
> +
> + if (Type >= NonDiscoverableDeviceTypeMax ||
> + DmaType >= NonDiscoverableDeviceDmaTypeMax ||
> + NumMmioResources == 0) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (Handle == NULL) {
> + Handle = &LocalHandle;
> + LocalHandle = NULL;
> + }
> +
> + AllocSize = sizeof *Device +
> + NumMmioResources * sizeof
> (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
> + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR); Device =
> + (NON_DISCOVERABLE_DEVICE *)AllocateZeroPool (AllocSize); if (Device
> + == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + Device->Type = GetGuidFromType (Type); ASSERT (Device->Type !=
> + NULL);
> +
> + Device->DmaType = DmaType;
> + Device->Initialize = InitFunc;
> + Device->Resources = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(Device
> +
> + 1);
> +
> + VA_START (Args, NumMmioResources);
> + for (Index = 0; Index < NumMmioResources; Index++) {
> + Desc = &Device->Resources [Index];
> + Base = VA_ARG (Args, UINTN);
> + Size = VA_ARG (Args, UINTN);
> +
> + Desc->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
> + Desc->Len = sizeof *Desc - 3;
> + Desc->AddrRangeMin = Base;
> + Desc->AddrLen = Size;
> + Desc->AddrRangeMax = Base + Size - 1;
> + Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
> + Desc->AddrSpaceGranularity = (Base + Size > SIZE_4GB) ? 64 : 32;
> + Desc->AddrTranslationOffset = 0;
> + }
> + VA_END (Args);
> +
> + End = (EFI_ACPI_END_TAG_DESCRIPTOR *)&Device->Resources
> + [NumMmioResources];
> +
> + End->Desc = ACPI_END_TAG_DESCRIPTOR;
> + End->Checksum = 0;
> +
> + DevicePath = (NON_DISCOVERABLE_DEVICE_PATH *)CreateDeviceNode (
> + HARDWARE_DEVICE_PATH,
> + HW_VENDOR_DP,
> + sizeof (*DevicePath));
> + if (DevicePath == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto FreeDevice;
> + }
> +
> + CopyGuid (&DevicePath->Vendor.Guid,
> + &gEdkiiNonDiscoverableDeviceProtocolGuid);
> +
> + //
> + // Use the base address and type of the first region to // make the
> + device path unique // DevicePath->BaseAddress = Device->Resources
> + [0].AddrRangeMin; DevicePath->ResourceType = Device->Resources
> + [0].ResType;
> +
> + SetDevicePathNodeLength (&DevicePath->Vendor,
> + sizeof (*DevicePath) - sizeof (DevicePath->End));
> + SetDevicePathEndNode (&DevicePath->End);
> +
> + Status = gBS->InstallMultipleProtocolInterfaces (Handle,
> + &gEdkiiNonDiscoverableDeviceProtocolGuid, Device,
> + &gEfiDevicePathProtocolGuid, DevicePath,
> + NULL);
> + if (EFI_ERROR (Status)) {
> + goto FreeDevicePath;
> + }
> + return EFI_SUCCESS;
> +
> +FreeDevicePath:
> + FreePool (DevicePath);
> +
> +FreeDevice:
> + FreePool (Device);
> +
> + return Status;
> +}
> diff --git
> a/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDisco
> verableDeviceRegistrationLib.inf
> b/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDisco
> verableDeviceRegistrationLib.inf
> new file mode 100644
> index 000000000000..ba32324c303e
> --- /dev/null
> +++
> b/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDisco
> +++ verableDeviceRegistrationLib.inf
> @@ -0,0 +1,46 @@
> +# @file
> +# Copyright (c) 2016, Linaro, Ltd. 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
> +#
> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +#
> +
> +[Defines]
> + INF_VERSION = 0x00010019
> + BASE_NAME = NonDiscoverableDeviceRegistrationLib
> + FILE_GUID = 8802ae41-8184-49cb-8aec-62627cd7ceb4
> + MODULE_TYPE = DXE_DRIVER
> + VERSION_STRING = 1.0
> + LIBRARY_CLASS = NonDiscoverableDeviceRegistrationLib
> +
> +[Sources]
> + NonDiscoverableDeviceRegistrationLib.c
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> + BaseMemoryLib
> + DebugLib
> + DevicePathLib
> + UefiBootServicesTableLib
> +
> +[Protocols]
> + gEdkiiNonDiscoverableDeviceProtocolGuid
> +
> +[Guids]
> + gEdkiiNonDiscoverableAhciDeviceGuid
> + gEdkiiNonDiscoverableAmbaDeviceGuid
> + gEdkiiNonDiscoverableEhciDeviceGuid
> + gEdkiiNonDiscoverableNvmeDeviceGuid
> + gEdkiiNonDiscoverableOhciDeviceGuid
> + gEdkiiNonDiscoverableSdhciDeviceGuid
> + gEdkiiNonDiscoverableUfsDeviceGuid
> + gEdkiiNonDiscoverableUhciDeviceGuid
> + gEdkiiNonDiscoverableXhciDeviceGuid
> diff --git a/MdeModulePkg/MdeModulePkg.dec
> b/MdeModulePkg/MdeModulePkg.dec index 588f5e97dbc2..315337fa4000
> 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -161,6 +161,10 @@ [LibraryClasses]
> #
> FmpAuthenticationLib|Include/Library/FmpAuthenticationLib.h
>
> + ## @libraryclass Provides a service to register non-discoverable device
> + ##
> +
> +
> NonDiscoverableDeviceRegistrationLib|Include/Library/NonDiscoverableDe
> + viceRegistrationLib.h
> +
> [Guids]
> ## MdeModule package token space guid
> # Include/Guid/MdeModulePkgTokenSpace.h
> diff --git a/MdeModulePkg/MdeModulePkg.dsc
> b/MdeModulePkg/MdeModulePkg.dsc index bfecb3078737..20e5e8c78be0
> 100644
> --- a/MdeModulePkg/MdeModulePkg.dsc
> +++ b/MdeModulePkg/MdeModulePkg.dsc
> @@ -102,6 +102,7 @@ [LibraryClasses]
>
> AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableL
> ibNull.inf
> VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
> FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
> +
> +
> NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscove
> ra
> + bleDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
>
>
> FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenticationLibNull/F
> mpAuthenticationLibNull.inf
>
> CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.i
> nf
> @@ -322,6 +323,7 @@ [Components]
> MdeModulePkg/Library/PeiIpmiLibIpmiPpi/PeiIpmiLibIpmiPpi.inf
>
> MdeModulePkg/Library/SmmIpmiLibSmmIpmiProtocol/SmmIpmiLibSmmIp
> miProtocol.inf
> MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
> +
> +
> MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscove
> ra
> + bleDeviceRegistrationLib.inf
>
> MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
>
> MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuAp
> p.inf
> --
> 2.7.4
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4 4/5] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA
2016-11-25 15:42 ` [PATCH v4 4/5] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Ard Biesheuvel
@ 2016-11-28 2:25 ` Ni, Ruiyu
0 siblings, 0 replies; 19+ messages in thread
From: Ni, Ruiyu @ 2016-11-28 2:25 UTC (permalink / raw)
To: Ard Biesheuvel, edk2-devel@lists.01.org, leif.lindholm@linaro.org,
Gao, Liming, afish@apple.com, Kinney, Michael D, mw@semihalf.com,
Tian, Feng
Comments in NonCoherentPciIoAllocateBuffer().
Thanks/Ray
> -----Original Message-----
> From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
> Sent: Friday, November 25, 2016 11:42 PM
> To: edk2-devel@lists.01.org; leif.lindholm@linaro.org; Gao, Liming
> <liming.gao@intel.com>; afish@apple.com; Ni, Ruiyu <ruiyu.ni@intel.com>;
> Kinney, Michael D <michael.d.kinney@intel.com>; mw@semihalf.com; Tian,
> Feng <feng.tian@intel.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Subject: [PATCH v4 4/5] MdeModulePkg/NonDiscoverablePciDeviceDxe: add
> support for non-coherent DMA
>
> Add support for non-coherent DMA, either by performing explicit cache
> maintenance when DMA mappings are aligned to the CPU's DMA buffer
> alignment, or by bounce buffering via uncached mappings otherwise.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
> DeviceDxe.c | 14 +-
>
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
> DeviceDxe.inf | 2 +
>
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
> DeviceIo.c | 319 ++++++++++++++++++++
>
> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
> DeviceIo.h | 29 ++
> 4 files changed, 357 insertions(+), 7 deletions(-)
>
> diff --git
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.c
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.c
> index ee765d7a5d9c..0fcf2b2ec1bf 100644
> ---
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.c
> +++
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> Pc
> +++ iDeviceDxe.c
> @@ -16,6 +16,8 @@
>
> #include <Protocol/DriverBinding.h>
>
> +EFI_CPU_ARCH_PROTOCOL *mCpu;
> +
> //
> // We only support the following device types // @@ -69,14 +71,7 @@
> NonDiscoverablePciDeviceSupported (
> return Status;
> }
>
> - //
> - // Restricted to DMA coherent for now
> - //
> Status = EFI_UNSUPPORTED;
> - if (Device->DmaType != NonDiscoverableDeviceDmaTypeCoherent) {
> - goto CloseProtocol;
> - }
> -
> for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++)
> {
> if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices [Idx]))
> {
> Status = EFI_SUCCESS;
> @@ -224,6 +219,11 @@ NonDiscoverablePciDeviceDxeEntryPoint (
> IN EFI_SYSTEM_TABLE *SystemTable
> )
> {
> + EFI_STATUS Status;
> +
> + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID
> + **)&mCpu); ASSERT_EFI_ERROR(Status);
> +
> return EfiLibInstallDriverBindingComponentName2 (
> ImageHandle,
> SystemTable,
> diff --git
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.inf
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.inf
> index 996fe310e0e3..5faa8945134c 100644
> ---
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.inf
> +++
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> Pc
> +++ iDeviceDxe.inf
> @@ -32,6 +32,7 @@ [Packages]
> [LibraryClasses]
> BaseMemoryLib
> DebugLib
> + DxeServicesTableLib
> MemoryAllocationLib
> UefiBootServicesTableLib
> UefiDriverEntryPoint
> @@ -40,6 +41,7 @@ [LibraryClasses]
> [Protocols]
> gEfiPciIoProtocolGuid ## BY_START
> gEdkiiNonDiscoverableDeviceProtocolGuid ## TO_START
> + gEfiCpuArchProtocolGuid ## CONSUMES
>
> [Guids]
> gEdkiiNonDiscoverableAhciDeviceGuid
> diff --git
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.c
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.c
> index fd59267a8d66..5a4861a17717 100644
> ---
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.c
> +++
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> Pc
> +++ iDeviceIo.c
> @@ -15,6 +15,8 @@
>
> #include "NonDiscoverablePciDeviceIo.h"
>
> +#include <Library/DxeServicesTableLib.h>
> +
> #include <IndustryStandard/Acpi.h>
>
> #include <Protocol/PciRootBridgeIo.h>
> @@ -523,6 +525,316 @@ CoherentPciIoFreeBuffer (
> return EFI_SUCCESS;
> }
>
> +STATIC
> +EFI_STATUS
> +NonCoherentPciIoFreeBuffer (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN UINTN Pages,
> + IN VOID *HostAddress
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + LIST_ENTRY *Entry;
> + EFI_STATUS Status;
> + NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;
> + BOOLEAN Found;
> +
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
> +
> + Found = FALSE;
> +
> + //
> + // Find the uncached allocation list entry associated // with this
> + allocation // for (Entry = Dev->UncachedAllocationList.ForwardLink;
> + Entry != &Dev->UncachedAllocationList;
> + Entry = Entry->ForwardLink) {
> +
> + Alloc = BASE_CR (Entry,
> NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION, List);
> + if (Alloc->HostAddress == HostAddress && Alloc->NumPages == Pages) {
> + //
> + // We are freeing the exact allocation we were given
> + // before by AllocateBuffer()
> + //
> + Found = TRUE;
> + break;
> + }
> + }
> +
> + if (!Found) {
> + ASSERT_EFI_ERROR (EFI_NOT_FOUND);
> + return EFI_NOT_FOUND;
> + }
> +
> + RemoveEntryList (&Alloc->List);
> +
> + Status = gDS->SetMemorySpaceAttributes (
> + (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
> + EFI_PAGES_TO_SIZE (Pages),
> + Alloc->Attributes);
> + if (EFI_ERROR (Status)) {
> + goto FreeAlloc;
> + }
> +
> + //
> + // If we fail to restore the original attributes, it is better to
> + leak the // memory than to return it to the heap // FreePages
> + (HostAddress, Pages);
> +
> +FreeAlloc:
> + FreePool (Alloc);
> + return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +NonCoherentPciIoAllocateBuffer (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_ALLOCATE_TYPE Type,
> + IN EFI_MEMORY_TYPE MemoryType,
> + IN UINTN Pages,
> + OUT VOID **HostAddress,
> + IN UINT64 Attributes
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
> + EFI_STATUS Status;
> + UINT64 MemType;
> + NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;
> +
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
> +
> + Status = CoherentPciIoAllocateBuffer (This, Type, MemoryType, Pages,
> + HostAddress, Attributes);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = gDS->GetMemorySpaceDescriptor (
> + (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
> + &GcdDescriptor);
> + if (EFI_ERROR (Status)) {
> + goto FreeBuffer;
1. in FreeBuffer, NonCoherentPciIoFreeBuffer() is called.
But since the allocation entry hasn't been allocated and inserted
to the list, the NonCoherentPciIoFreeBuffer() will assert and return
EFI_NOT_FOUND, resulting the memory leak.
> + }
> +
> + if ((GcdDescriptor.Capabilities & (EFI_MEMORY_WC | EFI_MEMORY_UC))
> == 0) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + //
> + // Set the preferred memory attributes // if ((Attributes &
> + EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE) != 0 ||
> + (GcdDescriptor.Capabilities & EFI_MEMORY_UC) == 0) {
> + //
> + // Use write combining if it was requested, or if it is the only
> + // type supported by the region.
> + //
> + MemType = EFI_MEMORY_WC;
> + } else {
> + MemType = EFI_MEMORY_UC;
> + }
> +
> + Alloc = AllocatePool (sizeof *Alloc); if (Alloc == NULL) {
> + goto FreeBuffer;
2. Same as #1.
Did you mean to call CoherentPciIoFreeBuffer()?
> + }
> +
> + Alloc->HostAddress = *HostAddress;
> + Alloc->NumPages = Pages;
> + Alloc->Attributes = GcdDescriptor.Attributes;
> +
> + //
> + // Record this allocation in the linked list, so we // can restore
> + the memory space attributes later // InsertHeadList
> + (&Dev->UncachedAllocationList, &Alloc->List);
> +
> + Status = gDS->SetMemorySpaceAttributes (
> + (EFI_PHYSICAL_ADDRESS)(UINTN)*HostAddress,
> + EFI_PAGES_TO_SIZE (Pages),
> + MemType);
> + if (EFI_ERROR (Status)) {
> + goto RemoveList;
3. same as #1.
> + }
> +
> + Status = mCpu->FlushDataCache (
> + mCpu,
> + (EFI_PHYSICAL_ADDRESS)(UINTN)*HostAddress,
> + EFI_PAGES_TO_SIZE (Pages),
> + EfiCpuFlushTypeInvalidate); if (EFI_ERROR (Status))
> + {
> + goto RemoveList;
4. same as #1.
> + }
> +
> + return EFI_SUCCESS;
> +
> +RemoveList:
> + RemoveEntryList (&Alloc->List);
> + FreePool (Alloc);
> +
> +FreeBuffer:
> + NonCoherentPciIoFreeBuffer (This, Pages, *HostAddress);
> + return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +NonCoherentPciIoMap (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
> + IN VOID *HostAddress,
> + IN OUT UINTN *NumberOfBytes,
> + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
> + OUT VOID **Mapping
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE *Dev;
> + EFI_STATUS Status;
> + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;
> + UINTN AlignMask;
> + VOID *AllocAddress;
> + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
> + BOOLEAN Bounce;
> +
> + MapInfo = AllocatePool (sizeof *MapInfo); if (MapInfo == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + MapInfo->HostAddress = HostAddress;
> + MapInfo->Operation = Operation;
> + MapInfo->NumberOfBytes = *NumberOfBytes;
> +
> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
> +
> + //
> + // If this device does not support 64-bit DMA addressing, we need to
> + allocate // a bounce buffer and copy over the data in case HostAddress >=
> 4 GB.
> + //
> + Bounce = ((Dev->Attributes &
> EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0 &&
> + (UINTN)HostAddress + *NumberOfBytes > SIZE_4GB);
> +
> + if (!Bounce) {
> + switch (Operation) {
> + case EfiPciIoOperationBusMasterRead:
> + case EfiPciIoOperationBusMasterWrite:
> + //
> + // For streaming DMA, it is sufficient if the buffer is aligned to
> + // the CPUs DMA buffer alignment.
> + //
> + AlignMask = mCpu->DmaBufferAlignment - 1;
> + if ((((UINTN) HostAddress | *NumberOfBytes) & AlignMask) == 0) {
> + break;
> + }
> + // fall through
> +
> + case EfiPciIoOperationBusMasterCommonBuffer:
> + //
> + // Check whether the host address refers to an uncached mapping.
> + //
> + Status = gDS->GetMemorySpaceDescriptor (
> + (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
> + &GcdDescriptor);
> + if (EFI_ERROR (Status) ||
> + (GcdDescriptor.Attributes &
> (EFI_MEMORY_WB|EFI_MEMORY_WT)) != 0) {
> + Bounce = TRUE;
> + }
> + break;
> +
> + default:
> + ASSERT (FALSE);
> + }
> + }
> +
> + if (Bounce) {
> + if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
> + Status = EFI_DEVICE_ERROR;
> + goto FreeMapInfo;
> + }
> +
> + Status = NonCoherentPciIoAllocateBuffer (This, AllocateAnyPages,
> + EfiBootServicesData, EFI_SIZE_TO_PAGES (MapInfo-
> >NumberOfBytes),
> + &AllocAddress, EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE);
> + if (EFI_ERROR (Status)) {
> + goto FreeMapInfo;
> + }
> + MapInfo->AllocAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress;
> + if (Operation == EfiPciIoOperationBusMasterRead) {
> + gBS->CopyMem (AllocAddress, HostAddress, *NumberOfBytes);
> + }
> + *DeviceAddress = MapInfo->AllocAddress; } else {
> + MapInfo->AllocAddress = 0;
> + *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
> +
> + //
> + // We are not using a bounce buffer: the mapping is sufficiently
> + // aligned to allow us to simply flush the caches. Note that cleaning
> + // the caches is necessary for both data directions:
> + // - for bus master read, we want the latest data to be present
> + // in main memory
> + // - for bus master write, we don't want any stale dirty cachelines that
> + // may be written back unexpectedly, and clobber the data written to
> + // main memory by the device.
> + //
> + mCpu->FlushDataCache (mCpu,
> (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
> + *NumberOfBytes, EfiCpuFlushTypeWriteBack); }
> +
> + *Mapping = MapInfo;
> + return EFI_SUCCESS;
> +
> +FreeMapInfo:
> + FreePool (MapInfo);
> +
> + return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +NonCoherentPciIoUnmap (
> + IN EFI_PCI_IO_PROTOCOL *This,
> + IN VOID *Mapping
> + )
> +{
> + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo;
> +
> + if (Mapping == NULL) {
> + return EFI_DEVICE_ERROR;
> + }
> +
> + MapInfo = Mapping;
> + if (MapInfo->AllocAddress != 0) {
> + //
> + // We are using a bounce buffer: copy back the data if necessary,
> + // and free the buffer.
> + //
> + if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {
> + gBS->CopyMem (MapInfo->HostAddress, (VOID *)(UINTN)MapInfo-
> >AllocAddress,
> + MapInfo->NumberOfBytes);
> + }
> + NonCoherentPciIoFreeBuffer (This,
> + EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),
> + (VOID *)(UINTN)MapInfo->AllocAddress);
> + } else {
> + //
> + // We are *not* using a bounce buffer: if this is a bus master write,
> + // we have to invalidate the caches so the CPU will see the uncached
> + // data written by the device.
> + //
> + if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {
> + mCpu->FlushDataCache (mCpu,
> + (EFI_PHYSICAL_ADDRESS)(UINTN)MapInfo->HostAddress,
> + MapInfo->NumberOfBytes, EfiCpuFlushTypeInvalidate);
> + }
> + }
> + FreePool (MapInfo);
> + return EFI_SUCCESS;
> +}
>
> STATIC
> EFI_STATUS
> @@ -715,6 +1027,13 @@ InitializePciIoProtocol (
> // Copy protocol structure
> CopyMem(&Dev->PciIo, &PciIoTemplate, sizeof PciIoTemplate);
>
> + if (Dev->Device->DmaType ==
> NonDiscoverableDeviceDmaTypeNonCoherent) {
> + Dev->PciIo.AllocateBuffer = NonCoherentPciIoAllocateBuffer;
> + Dev->PciIo.FreeBuffer = NonCoherentPciIoFreeBuffer;
> + Dev->PciIo.Map = NonCoherentPciIoMap;
> + Dev->PciIo.Unmap = NonCoherentPciIoUnmap;
> + }
> +
> if (CompareGuid (Dev->Device->Type,
> &gEdkiiNonDiscoverableAhciDeviceGuid)) {
> Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_MASS_STORAGE_AHCI;
> Dev->ConfigSpace.Hdr.ClassCode[1] =
> PCI_CLASS_MASS_STORAGE_SATADPA; diff --git
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.h
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.h
> index bc0a3d3258f9..449614862911 100644
> ---
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceIo.h
> +++
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> Pc
> +++ iDeviceIo.h
> @@ -15,6 +15,8 @@
> #ifndef __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
> #define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
>
> +#include <PiDxe.h>
> +
> #include <Library/BaseMemoryLib.h>
> #include <Library/DebugLib.h>
> #include <Library/MemoryAllocationLib.h> @@ -25,6 +27,7 @@
>
> #include <Protocol/ComponentName.h>
> #include <Protocol/NonDiscoverableDevice.h>
> +#include <Protocol/Cpu.h>
> #include <Protocol/PciIo.h>
>
> #define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I',
> 'D') @@ -38,6 +41,27 @@
>
> #define PCI_MAX_BARS 6
>
> +extern EFI_CPU_ARCH_PROTOCOL *mCpu;
> +
> +typedef struct {
> + //
> + // The linked-list next pointer
> + //
> + LIST_ENTRY List;
> + //
> + // The address of the uncached allocation
> + //
> + VOID *HostAddress;
> + //
> + // The number of pages in the allocation
> + //
> + UINTN NumPages;
> + //
> + // The attributes of the allocation
> + //
> + UINT64 Attributes;
> +} NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION;
> +
> typedef struct {
> UINT32 Signature;
> //
> @@ -71,6 +95,11 @@ typedef struct {
> // Whether this device has been enabled
> //
> BOOLEAN Enabled;
> + //
> + // Linked list to keep track of uncached allocations performed // on
> + behalf of this device //
> + LIST_ENTRY UncachedAllocationList;
> } NON_DISCOVERABLE_PCI_DEVICE;
>
> VOID
> --
> 2.7.4
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4 3/5] MdeModulePkg: implement generic PCI I/O driver for non-discoverable devices
2016-11-28 1:56 ` Ni, Ruiyu
@ 2016-11-30 14:06 ` Leif Lindholm
2016-12-02 10:09 ` Leif Lindholm
2016-12-02 12:54 ` Ni, Ruiyu
0 siblings, 2 replies; 19+ messages in thread
From: Leif Lindholm @ 2016-11-30 14:06 UTC (permalink / raw)
To: Ni, Ruiyu
Cc: Ard Biesheuvel, edk2-devel@lists.01.org, Gao, Liming,
afish@apple.com, Kinney, Michael D, mw@semihalf.com, Tian, Feng
Hi Ray,
Ard is on holiday this week, and mostly managing to stay off the
email...
Anyway, I could really use this support in order to bring the Marvell
Armada 70x0 support (worked on by the Semihalf guys) into
OpenPlatformPkg, so I will pick this up while he is away - at least
parts 1-3.
4/5 is required for 5/5, so I will not be looking to push the final
one myself.
Would you OK with pushing just 1-3 once we get this one resolved?
On Mon, Nov 28, 2016 at 01:56:21AM +0000, Ni, Ruiyu wrote:
> > diff --git
> > a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> > PciDeviceIo.c
> > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> > PciDeviceIo.c
> > new file mode 100644
> > index 000000000000..fd59267a8d66
> > --- /dev/null
> > +++
> > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> > Pc
> > +++ iDeviceIo.c
> > @@ -0,0 +1,797 @@
...
> > +VOID
> > +InitializePciIoProtocol (
> > + NON_DISCOVERABLE_PCI_DEVICE *Dev
> > + )
> > +{
> > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
> > + INTN Idx;
> > +
> > + InitializeListHead (&Dev->UncachedAllocationList);
The above line has crept in here, but belongs to 4/5 (causes
compilation error). I will fix that and resend - is it OK if I resend
this patch only?
> > + // Iterate over the resources to populate the virtual BARs
> > + //
> > + Idx = Dev->BarOffset;
> > + for (Desc = Dev->Device->Resources, Dev->BarCount = 0;
> > + Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
> > + Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {
> > +
> > + ASSERT (Desc->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR);
> > + ASSERT (Desc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM);
> > +
> > + if (Idx >= PCI_MAX_BARS ||
> > + (Idx == PCI_MAX_BARS - 1 && Desc->AddrSpaceGranularity == 64)) {
> > + DEBUG ((DEBUG_ERROR,
> > + "%a: resource count exceeds number of emulated BARs\n",
> > + __FUNCTION__));
> > + ASSERT (FALSE);
> > + break;
> > + }
> > +
> > + Dev->ConfigSpace.Device.Bar[Idx] = (UINT32)Desc->AddrRangeMin;
> > + Dev->BarCount++;
> > +
> > + if (Desc->AddrSpaceGranularity == 64) {
> > + Dev->ConfigSpace.Device.Bar[Idx] |= 0x4;
> > + Dev->ConfigSpace.Device.Bar[++Idx] = (UINT32)(Desc->AddrRangeMin >> 32);
>
> 1. You need to use RShiftU64 otherwise the above code will break the
> build process in 32bit.
I don't understand how that could cause breakage (and experiments with
IA32 and ARM fail to reproduce it with GCC).
- Bar[x] is an array of UINT32
- Desc->AddrRangeMin is UINT64
- The result of (Desc->AddrRangeMin >> 32) is explicitly cast to
UINT32 (the type of Bar[x]).
Is the problem related to the shift value being signed?
Or does some other compiler refuse to cast a UINT64 to a UINT32?
Regards,
Leif
> > + }
> > + }
> > +}
> > diff --git
> > a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> > PciDeviceIo.h
> > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> > PciDeviceIo.h
> > new file mode 100644
> > index 000000000000..bc0a3d3258f9
> > --- /dev/null
> > +++
> > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> > Pc
> > +++ iDeviceIo.h
> > @@ -0,0 +1,84 @@
> > +/** @file
> > +
> > + Copyright (C) 2016, Linaro Ltd. 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
> > +
> > + 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 __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
> > +#define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
> > +
> > +#include <Library/BaseMemoryLib.h>
> > +#include <Library/DebugLib.h>
> > +#include <Library/MemoryAllocationLib.h> #include
> > +<Library/UefiBootServicesTableLib.h>
> > +#include <Library/UefiLib.h>
> > +
> > +#include <IndustryStandard/Pci.h>
> > +
> > +#include <Protocol/ComponentName.h>
> > +#include <Protocol/NonDiscoverableDevice.h>
> > +#include <Protocol/PciIo.h>
> > +
> > +#define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I',
> > +'D')
> > +
> > +#define NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(PciIoPointer) \
> > + CR (PciIoPointer, NON_DISCOVERABLE_PCI_DEVICE, PciIo, \
> > + NON_DISCOVERABLE_PCI_DEVICE_SIG)
> > +
> > +#define PCI_ID_VENDOR_UNKNOWN 0xffff
> > +#define PCI_ID_DEVICE_DONTCARE 0x0000
> > +
> > +#define PCI_MAX_BARS 6
> > +
> > +typedef struct {
> > + UINT32 Signature;
> > + //
> > + // The bound non-discoverable device protocol instance
> > + //
> > + NON_DISCOVERABLE_DEVICE *Device;
> > + //
> > + // The exposed PCI I/O protocol instance.
> > + //
> > + EFI_PCI_IO_PROTOCOL PciIo;
> > + //
> > + // The emulated PCI config space of the device. Only the minimally
> > +required
> > + // items are assigned.
> > + //
> > + PCI_TYPE00 ConfigSpace;
> > + //
> > + // The first virtual BAR to assign based on the resources described
> > + // by the non-discoverable device.
> > + //
> > + UINT32 BarOffset;
> > + //
> > + // The number of virtual BARs we expose based on the number of
> > + // resources
> > + //
> > + UINT32 BarCount;
> > + //
> > + // The PCI I/O attributes for this device
> > + //
> > + UINT64 Attributes;
> > + //
> > + // Whether this device has been enabled
> > + //
> > + BOOLEAN Enabled;
> > +} NON_DISCOVERABLE_PCI_DEVICE;
> > +
> > +VOID
> > +InitializePciIoProtocol (
> > + NON_DISCOVERABLE_PCI_DEVICE *Device
> > + );
> > +
> > +extern EFI_COMPONENT_NAME_PROTOCOL gComponentName; extern
> > +EFI_COMPONENT_NAME2_PROTOCOL gComponentName2;
> > +
> > +#endif
> > diff --git a/MdeModulePkg/MdeModulePkg.dsc
> > b/MdeModulePkg/MdeModulePkg.dsc index 20e5e8c78be0..5dd30556cb3c
> > 100644
> > --- a/MdeModulePkg/MdeModulePkg.dsc
> > +++ b/MdeModulePkg/MdeModulePkg.dsc
> > @@ -265,6 +265,7 @@ [Components]
> > MdeModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf
> > MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
> > MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
> > +
> > +
> > MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
> > Dev
> > + iceDxe.inf
> >
> > MdeModulePkg/Core/Dxe/DxeMain.inf {
> > <LibraryClasses>
> > --
> > 2.7.4
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4 3/5] MdeModulePkg: implement generic PCI I/O driver for non-discoverable devices
2016-11-30 14:06 ` Leif Lindholm
@ 2016-12-02 10:09 ` Leif Lindholm
2016-12-02 12:54 ` Ni, Ruiyu
1 sibling, 0 replies; 19+ messages in thread
From: Leif Lindholm @ 2016-12-02 10:09 UTC (permalink / raw)
To: Ni, Ruiyu
Cc: Ard Biesheuvel, edk2-devel@lists.01.org, Gao, Liming,
afish@apple.com, Kinney, Michael D, mw@semihalf.com, Tian, Feng
Ray, any comments on the below?
Regards,
Leif
On Wed, Nov 30, 2016 at 02:06:55PM +0000, Leif Lindholm wrote:
> Hi Ray,
>
> Ard is on holiday this week, and mostly managing to stay off the
> email...
>
> Anyway, I could really use this support in order to bring the Marvell
> Armada 70x0 support (worked on by the Semihalf guys) into
> OpenPlatformPkg, so I will pick this up while he is away - at least
> parts 1-3.
>
> 4/5 is required for 5/5, so I will not be looking to push the final
> one myself.
>
> Would you OK with pushing just 1-3 once we get this one resolved?
>
> On Mon, Nov 28, 2016 at 01:56:21AM +0000, Ni, Ruiyu wrote:
> > > diff --git
> > > a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> > > PciDeviceIo.c
> > > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> > > PciDeviceIo.c
> > > new file mode 100644
> > > index 000000000000..fd59267a8d66
> > > --- /dev/null
> > > +++
> > > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> > > Pc
> > > +++ iDeviceIo.c
> > > @@ -0,0 +1,797 @@
> ...
> > > +VOID
> > > +InitializePciIoProtocol (
> > > + NON_DISCOVERABLE_PCI_DEVICE *Dev
> > > + )
> > > +{
> > > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
> > > + INTN Idx;
> > > +
> > > + InitializeListHead (&Dev->UncachedAllocationList);
>
> The above line has crept in here, but belongs to 4/5 (causes
> compilation error). I will fix that and resend - is it OK if I resend
> this patch only?
>
> > > + // Iterate over the resources to populate the virtual BARs
> > > + //
> > > + Idx = Dev->BarOffset;
> > > + for (Desc = Dev->Device->Resources, Dev->BarCount = 0;
> > > + Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
> > > + Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {
> > > +
> > > + ASSERT (Desc->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR);
> > > + ASSERT (Desc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM);
> > > +
> > > + if (Idx >= PCI_MAX_BARS ||
> > > + (Idx == PCI_MAX_BARS - 1 && Desc->AddrSpaceGranularity == 64)) {
> > > + DEBUG ((DEBUG_ERROR,
> > > + "%a: resource count exceeds number of emulated BARs\n",
> > > + __FUNCTION__));
> > > + ASSERT (FALSE);
> > > + break;
> > > + }
> > > +
> > > + Dev->ConfigSpace.Device.Bar[Idx] = (UINT32)Desc->AddrRangeMin;
> > > + Dev->BarCount++;
> > > +
> > > + if (Desc->AddrSpaceGranularity == 64) {
> > > + Dev->ConfigSpace.Device.Bar[Idx] |= 0x4;
> > > + Dev->ConfigSpace.Device.Bar[++Idx] = (UINT32)(Desc->AddrRangeMin >> 32);
> >
> > 1. You need to use RShiftU64 otherwise the above code will break the
> > build process in 32bit.
>
> I don't understand how that could cause breakage (and experiments with
> IA32 and ARM fail to reproduce it with GCC).
>
> - Bar[x] is an array of UINT32
> - Desc->AddrRangeMin is UINT64
> - The result of (Desc->AddrRangeMin >> 32) is explicitly cast to
> UINT32 (the type of Bar[x]).
>
> Is the problem related to the shift value being signed?
> Or does some other compiler refuse to cast a UINT64 to a UINT32?
>
> Regards,
>
> Leif
>
> > > + }
> > > + }
> > > +}
> > > diff --git
> > > a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> > > PciDeviceIo.h
> > > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> > > PciDeviceIo.h
> > > new file mode 100644
> > > index 000000000000..bc0a3d3258f9
> > > --- /dev/null
> > > +++
> > > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> > > Pc
> > > +++ iDeviceIo.h
> > > @@ -0,0 +1,84 @@
> > > +/** @file
> > > +
> > > + Copyright (C) 2016, Linaro Ltd. 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
> > > +
> > > + 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 __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
> > > +#define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
> > > +
> > > +#include <Library/BaseMemoryLib.h>
> > > +#include <Library/DebugLib.h>
> > > +#include <Library/MemoryAllocationLib.h> #include
> > > +<Library/UefiBootServicesTableLib.h>
> > > +#include <Library/UefiLib.h>
> > > +
> > > +#include <IndustryStandard/Pci.h>
> > > +
> > > +#include <Protocol/ComponentName.h>
> > > +#include <Protocol/NonDiscoverableDevice.h>
> > > +#include <Protocol/PciIo.h>
> > > +
> > > +#define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I',
> > > +'D')
> > > +
> > > +#define NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(PciIoPointer) \
> > > + CR (PciIoPointer, NON_DISCOVERABLE_PCI_DEVICE, PciIo, \
> > > + NON_DISCOVERABLE_PCI_DEVICE_SIG)
> > > +
> > > +#define PCI_ID_VENDOR_UNKNOWN 0xffff
> > > +#define PCI_ID_DEVICE_DONTCARE 0x0000
> > > +
> > > +#define PCI_MAX_BARS 6
> > > +
> > > +typedef struct {
> > > + UINT32 Signature;
> > > + //
> > > + // The bound non-discoverable device protocol instance
> > > + //
> > > + NON_DISCOVERABLE_DEVICE *Device;
> > > + //
> > > + // The exposed PCI I/O protocol instance.
> > > + //
> > > + EFI_PCI_IO_PROTOCOL PciIo;
> > > + //
> > > + // The emulated PCI config space of the device. Only the minimally
> > > +required
> > > + // items are assigned.
> > > + //
> > > + PCI_TYPE00 ConfigSpace;
> > > + //
> > > + // The first virtual BAR to assign based on the resources described
> > > + // by the non-discoverable device.
> > > + //
> > > + UINT32 BarOffset;
> > > + //
> > > + // The number of virtual BARs we expose based on the number of
> > > + // resources
> > > + //
> > > + UINT32 BarCount;
> > > + //
> > > + // The PCI I/O attributes for this device
> > > + //
> > > + UINT64 Attributes;
> > > + //
> > > + // Whether this device has been enabled
> > > + //
> > > + BOOLEAN Enabled;
> > > +} NON_DISCOVERABLE_PCI_DEVICE;
> > > +
> > > +VOID
> > > +InitializePciIoProtocol (
> > > + NON_DISCOVERABLE_PCI_DEVICE *Device
> > > + );
> > > +
> > > +extern EFI_COMPONENT_NAME_PROTOCOL gComponentName; extern
> > > +EFI_COMPONENT_NAME2_PROTOCOL gComponentName2;
> > > +
> > > +#endif
> > > diff --git a/MdeModulePkg/MdeModulePkg.dsc
> > > b/MdeModulePkg/MdeModulePkg.dsc index 20e5e8c78be0..5dd30556cb3c
> > > 100644
> > > --- a/MdeModulePkg/MdeModulePkg.dsc
> > > +++ b/MdeModulePkg/MdeModulePkg.dsc
> > > @@ -265,6 +265,7 @@ [Components]
> > > MdeModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf
> > > MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
> > > MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
> > > +
> > > +
> > > MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
> > > Dev
> > > + iceDxe.inf
> > >
> > > MdeModulePkg/Core/Dxe/DxeMain.inf {
> > > <LibraryClasses>
> > > --
> > > 2.7.4
> >
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4 3/5] MdeModulePkg: implement generic PCI I/O driver for non-discoverable devices
2016-11-30 14:06 ` Leif Lindholm
2016-12-02 10:09 ` Leif Lindholm
@ 2016-12-02 12:54 ` Ni, Ruiyu
2016-12-02 14:40 ` Leif Lindholm
1 sibling, 1 reply; 19+ messages in thread
From: Ni, Ruiyu @ 2016-12-02 12:54 UTC (permalink / raw)
To: Leif Lindholm
Cc: Ard Biesheuvel, edk2-devel@lists.01.org, Gao, Liming,
afish@apple.com, Kinney, Michael D, mw@semihalf.com, Tian, Feng
Regards,
Ray
>-----Original Message-----
>From: Leif Lindholm [mailto:leif.lindholm@linaro.org]
>Sent: Wednesday, November 30, 2016 10:07 PM
>To: Ni, Ruiyu <ruiyu.ni@intel.com>
>Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>; edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>;
>afish@apple.com; Kinney, Michael D <michael.d.kinney@intel.com>; mw@semihalf.com; Tian, Feng <feng.tian@intel.com>
>Subject: Re: [PATCH v4 3/5] MdeModulePkg: implement generic PCI I/O driver for non-discoverable devices
>
>Hi Ray,
>
>Ard is on holiday this week, and mostly managing to stay off the
>email...
>
>Anyway, I could really use this support in order to bring the Marvell
>Armada 70x0 support (worked on by the Semihalf guys) into
>OpenPlatformPkg, so I will pick this up while he is away - at least
>parts 1-3.
>
>4/5 is required for 5/5, so I will not be looking to push the final
>one myself.
>
>Would you OK with pushing just 1-3 once we get this one resolved?
>
>On Mon, Nov 28, 2016 at 01:56:21AM +0000, Ni, Ruiyu wrote:
>> > diff --git
>> > a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> > PciDeviceIo.c
>> > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> > PciDeviceIo.c
>> > new file mode 100644
>> > index 000000000000..fd59267a8d66
>> > --- /dev/null
>> > +++
>> > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> > Pc
>> > +++ iDeviceIo.c
>> > @@ -0,0 +1,797 @@
>...
>> > +VOID
>> > +InitializePciIoProtocol (
>> > + NON_DISCOVERABLE_PCI_DEVICE *Dev
>> > + )
>> > +{
>> > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
>> > + INTN Idx;
>> > +
>> > + InitializeListHead (&Dev->UncachedAllocationList);
>
>The above line has crept in here, but belongs to 4/5 (causes
>compilation error). I will fix that and resend - is it OK if I resend
>this patch only?
>
>> > + // Iterate over the resources to populate the virtual BARs
>> > + //
>> > + Idx = Dev->BarOffset;
>> > + for (Desc = Dev->Device->Resources, Dev->BarCount = 0;
>> > + Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
>> > + Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {
>> > +
>> > + ASSERT (Desc->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR);
>> > + ASSERT (Desc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM);
>> > +
>> > + if (Idx >= PCI_MAX_BARS ||
>> > + (Idx == PCI_MAX_BARS - 1 && Desc->AddrSpaceGranularity == 64)) {
>> > + DEBUG ((DEBUG_ERROR,
>> > + "%a: resource count exceeds number of emulated BARs\n",
>> > + __FUNCTION__));
>> > + ASSERT (FALSE);
>> > + break;
>> > + }
>> > +
>> > + Dev->ConfigSpace.Device.Bar[Idx] = (UINT32)Desc->AddrRangeMin;
>> > + Dev->BarCount++;
>> > +
>> > + if (Desc->AddrSpaceGranularity == 64) {
>> > + Dev->ConfigSpace.Device.Bar[Idx] |= 0x4;
>> > + Dev->ConfigSpace.Device.Bar[++Idx] = (UINT32)(Desc->AddrRangeMin >> 32);
>>
>> 1. You need to use RShiftU64 otherwise the above code will break the
>> build process in 32bit.
>
>I don't understand how that could cause breakage (and experiments with
>IA32 and ARM fail to reproduce it with GCC).
>
>- Bar[x] is an array of UINT32
>- Desc->AddrRangeMin is UINT64
>- The result of (Desc->AddrRangeMin >> 32) is explicitly cast to
> UINT32 (the type of Bar[x]).
>
>Is the problem related to the shift value being signed?
>Or does some other compiler refuse to cast a UINT64 to a UINT32?
Desc->AddrRangeMin is UINT64. My experience tells me that
LShiftU64 or RShiftU64 should be used for shifting operation
on UINT64.
I guess the GCC might cleverly recognizes the ">>32" actually
picks up the high-32 bits so in 32bit environment, it just uses
value of the register which stores the high-32 bits.
Can you check the assembly code GCC generates?
or simply can you change ">>32" to ">>31" or ">>33" to see
what happens?
>
>Regards,
>
>Leif
>
>> > + }
>> > + }
>> > +}
>> > diff --git
>> > a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> > PciDeviceIo.h
>> > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> > PciDeviceIo.h
>> > new file mode 100644
>> > index 000000000000..bc0a3d3258f9
>> > --- /dev/null
>> > +++
>> > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> > Pc
>> > +++ iDeviceIo.h
>> > @@ -0,0 +1,84 @@
>> > +/** @file
>> > +
>> > + Copyright (C) 2016, Linaro Ltd. 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
>> > +
>> > + 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 __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
>> > +#define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
>> > +
>> > +#include <Library/BaseMemoryLib.h>
>> > +#include <Library/DebugLib.h>
>> > +#include <Library/MemoryAllocationLib.h> #include
>> > +<Library/UefiBootServicesTableLib.h>
>> > +#include <Library/UefiLib.h>
>> > +
>> > +#include <IndustryStandard/Pci.h>
>> > +
>> > +#include <Protocol/ComponentName.h>
>> > +#include <Protocol/NonDiscoverableDevice.h>
>> > +#include <Protocol/PciIo.h>
>> > +
>> > +#define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I',
>> > +'D')
>> > +
>> > +#define NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(PciIoPointer) \
>> > + CR (PciIoPointer, NON_DISCOVERABLE_PCI_DEVICE, PciIo, \
>> > + NON_DISCOVERABLE_PCI_DEVICE_SIG)
>> > +
>> > +#define PCI_ID_VENDOR_UNKNOWN 0xffff
>> > +#define PCI_ID_DEVICE_DONTCARE 0x0000
>> > +
>> > +#define PCI_MAX_BARS 6
>> > +
>> > +typedef struct {
>> > + UINT32 Signature;
>> > + //
>> > + // The bound non-discoverable device protocol instance
>> > + //
>> > + NON_DISCOVERABLE_DEVICE *Device;
>> > + //
>> > + // The exposed PCI I/O protocol instance.
>> > + //
>> > + EFI_PCI_IO_PROTOCOL PciIo;
>> > + //
>> > + // The emulated PCI config space of the device. Only the minimally
>> > +required
>> > + // items are assigned.
>> > + //
>> > + PCI_TYPE00 ConfigSpace;
>> > + //
>> > + // The first virtual BAR to assign based on the resources described
>> > + // by the non-discoverable device.
>> > + //
>> > + UINT32 BarOffset;
>> > + //
>> > + // The number of virtual BARs we expose based on the number of
>> > + // resources
>> > + //
>> > + UINT32 BarCount;
>> > + //
>> > + // The PCI I/O attributes for this device
>> > + //
>> > + UINT64 Attributes;
>> > + //
>> > + // Whether this device has been enabled
>> > + //
>> > + BOOLEAN Enabled;
>> > +} NON_DISCOVERABLE_PCI_DEVICE;
>> > +
>> > +VOID
>> > +InitializePciIoProtocol (
>> > + NON_DISCOVERABLE_PCI_DEVICE *Device
>> > + );
>> > +
>> > +extern EFI_COMPONENT_NAME_PROTOCOL gComponentName; extern
>> > +EFI_COMPONENT_NAME2_PROTOCOL gComponentName2;
>> > +
>> > +#endif
>> > diff --git a/MdeModulePkg/MdeModulePkg.dsc
>> > b/MdeModulePkg/MdeModulePkg.dsc index 20e5e8c78be0..5dd30556cb3c
>> > 100644
>> > --- a/MdeModulePkg/MdeModulePkg.dsc
>> > +++ b/MdeModulePkg/MdeModulePkg.dsc
>> > @@ -265,6 +265,7 @@ [Components]
>> > MdeModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf
>> > MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
>> > MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
>> > +
>> > +
>> > MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
>> > Dev
>> > + iceDxe.inf
>> >
>> > MdeModulePkg/Core/Dxe/DxeMain.inf {
>> > <LibraryClasses>
>> > --
>> > 2.7.4
>>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4 3/5] MdeModulePkg: implement generic PCI I/O driver for non-discoverable devices
2016-12-02 12:54 ` Ni, Ruiyu
@ 2016-12-02 14:40 ` Leif Lindholm
2016-12-02 15:07 ` Ard Biesheuvel
0 siblings, 1 reply; 19+ messages in thread
From: Leif Lindholm @ 2016-12-02 14:40 UTC (permalink / raw)
To: Ni, Ruiyu
Cc: Ard Biesheuvel, edk2-devel@lists.01.org, Gao, Liming,
afish@apple.com, Kinney, Michael D, mw@semihalf.com, Tian, Feng
On Fri, Dec 02, 2016 at 12:54:45PM +0000, Ni, Ruiyu wrote:
> >> > + Dev->ConfigSpace.Device.Bar[Idx] = (UINT32)Desc->AddrRangeMin;
> >> > + Dev->BarCount++;
> >> > +
> >> > + if (Desc->AddrSpaceGranularity == 64) {
> >> > + Dev->ConfigSpace.Device.Bar[Idx] |= 0x4;
> >> > + Dev->ConfigSpace.Device.Bar[++Idx] = (UINT32)(Desc->AddrRangeMin >> 32);
> >>
> >> 1. You need to use RShiftU64 otherwise the above code will break the
> >> build process in 32bit.
> >
> >I don't understand how that could cause breakage (and experiments with
> >IA32 and ARM fail to reproduce it with GCC).
> >
> >- Bar[x] is an array of UINT32
> >- Desc->AddrRangeMin is UINT64
> >- The result of (Desc->AddrRangeMin >> 32) is explicitly cast to
> > UINT32 (the type of Bar[x]).
> >
> >Is the problem related to the shift value being signed?
> >Or does some other compiler refuse to cast a UINT64 to a UINT32?
>
> Desc->AddrRangeMin is UINT64. My experience tells me that
> LShiftU64 or RShiftU64 should be used for shifting operation
> on UINT64.
This is the bit that confuses me. There is no such automatic
limitation in the C language (if long long is supported at all). So if
we're working around some bug in a specific compiler - I am happy to
do so. I just prefer knowing why rather than cargo-culting.
> I guess the GCC might cleverly recognizes the ">>32" actually
> picks up the high-32 bits so in 32bit environment, it just uses
> value of the register which stores the high-32 bits.
> Can you check the assembly code GCC generates?
> or simply can you change ">>32" to ">>31" or ">>33" to see
> what happens?
There is no cleverness required, it's just a defined operation on a
base type. But sure, for example:
unsigned int shift(long long val)
{
return (val >> 33);
}
decodes as
---
0000000000000000 <shift>:
0: 48 89 f8 mov %rdi,%rax
3: 48 c1 f8 21 sar $0x21,%rax
7: c3 retq
---
(in x86_64, using gcc -O2 to get rid of some redundant stack
operations)
The only thing that changes if the shift value is modified is that the
0x21 is changed accordingly.
Change it to an inline constant, not much changes:
unsigned int shiftconst(void)
{
unsigned long long var = 0xaaaabbbbccccddddULL;
return (var >> 31);
}
decodes as
---
0000000000000000 <shiftconst>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 b8 dd dd cc cc bb movabs $0xaaaabbbbccccdddd,%rax
b: bb aa aa
e: 48 89 45 f8 mov %rax,-0x8(%rbp)
12: 48 8b 45 f8 mov -0x8(%rbp),%rax
16: 48 c1 e8 1f shr $0x1f,%rax
1a: 5d pop %rbp
1b: c3 retq
---
(with -O0, to prevent the compiler from just doing the arithmetic
compile time)
Both also compile correctly for IA32 with -m32.
The point is that there is nothing clever here for the compiler to do:
casting a 64-bit int to a 32-bit int is an operation that discards the
top 32 bits - but the behaviour is entirely defined.
In fact, all architectures other than IA32/ARM use the Math64.c
implementation of RShiftU64, which simply does the shift.
And ARM does it only for GCC. I'm not sure why, I can't imagine a GCC
version that would do anything more complicated than
---
00000000 <shift>:
0: e1a000c1 asr r0, r1, #1
4: e12fff1e bx lr
---
(and that's with -march=armv4t onwards).
So if we are saying that there are certain specific compilers that do
not support 64-bit arithmetic for 32-bit architectures, and that those
compilers are still supported by BaseTools - then I'm fine with that.
But I don't want to replace functional C code with abstraction
functions without a proper understanding of where it would be
problematic.
Regards,
Leif
>
> >
> >Regards,
> >
> >Leif
> >
> >> > + }
> >> > + }
> >> > +}
> >> > diff --git
> >> > a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> >> > PciDeviceIo.h
> >> > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> >> > PciDeviceIo.h
> >> > new file mode 100644
> >> > index 000000000000..bc0a3d3258f9
> >> > --- /dev/null
> >> > +++
> >> > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> >> > Pc
> >> > +++ iDeviceIo.h
> >> > @@ -0,0 +1,84 @@
> >> > +/** @file
> >> > +
> >> > + Copyright (C) 2016, Linaro Ltd. 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
> >> > +
> >> > + 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 __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
> >> > +#define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
> >> > +
> >> > +#include <Library/BaseMemoryLib.h>
> >> > +#include <Library/DebugLib.h>
> >> > +#include <Library/MemoryAllocationLib.h> #include
> >> > +<Library/UefiBootServicesTableLib.h>
> >> > +#include <Library/UefiLib.h>
> >> > +
> >> > +#include <IndustryStandard/Pci.h>
> >> > +
> >> > +#include <Protocol/ComponentName.h>
> >> > +#include <Protocol/NonDiscoverableDevice.h>
> >> > +#include <Protocol/PciIo.h>
> >> > +
> >> > +#define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I',
> >> > +'D')
> >> > +
> >> > +#define NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(PciIoPointer) \
> >> > + CR (PciIoPointer, NON_DISCOVERABLE_PCI_DEVICE, PciIo, \
> >> > + NON_DISCOVERABLE_PCI_DEVICE_SIG)
> >> > +
> >> > +#define PCI_ID_VENDOR_UNKNOWN 0xffff
> >> > +#define PCI_ID_DEVICE_DONTCARE 0x0000
> >> > +
> >> > +#define PCI_MAX_BARS 6
> >> > +
> >> > +typedef struct {
> >> > + UINT32 Signature;
> >> > + //
> >> > + // The bound non-discoverable device protocol instance
> >> > + //
> >> > + NON_DISCOVERABLE_DEVICE *Device;
> >> > + //
> >> > + // The exposed PCI I/O protocol instance.
> >> > + //
> >> > + EFI_PCI_IO_PROTOCOL PciIo;
> >> > + //
> >> > + // The emulated PCI config space of the device. Only the minimally
> >> > +required
> >> > + // items are assigned.
> >> > + //
> >> > + PCI_TYPE00 ConfigSpace;
> >> > + //
> >> > + // The first virtual BAR to assign based on the resources described
> >> > + // by the non-discoverable device.
> >> > + //
> >> > + UINT32 BarOffset;
> >> > + //
> >> > + // The number of virtual BARs we expose based on the number of
> >> > + // resources
> >> > + //
> >> > + UINT32 BarCount;
> >> > + //
> >> > + // The PCI I/O attributes for this device
> >> > + //
> >> > + UINT64 Attributes;
> >> > + //
> >> > + // Whether this device has been enabled
> >> > + //
> >> > + BOOLEAN Enabled;
> >> > +} NON_DISCOVERABLE_PCI_DEVICE;
> >> > +
> >> > +VOID
> >> > +InitializePciIoProtocol (
> >> > + NON_DISCOVERABLE_PCI_DEVICE *Device
> >> > + );
> >> > +
> >> > +extern EFI_COMPONENT_NAME_PROTOCOL gComponentName; extern
> >> > +EFI_COMPONENT_NAME2_PROTOCOL gComponentName2;
> >> > +
> >> > +#endif
> >> > diff --git a/MdeModulePkg/MdeModulePkg.dsc
> >> > b/MdeModulePkg/MdeModulePkg.dsc index 20e5e8c78be0..5dd30556cb3c
> >> > 100644
> >> > --- a/MdeModulePkg/MdeModulePkg.dsc
> >> > +++ b/MdeModulePkg/MdeModulePkg.dsc
> >> > @@ -265,6 +265,7 @@ [Components]
> >> > MdeModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf
> >> > MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
> >> > MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
> >> > +
> >> > +
> >> > MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
> >> > Dev
> >> > + iceDxe.inf
> >> >
> >> > MdeModulePkg/Core/Dxe/DxeMain.inf {
> >> > <LibraryClasses>
> >> > --
> >> > 2.7.4
> >>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4 3/5] MdeModulePkg: implement generic PCI I/O driver for non-discoverable devices
2016-12-02 14:40 ` Leif Lindholm
@ 2016-12-02 15:07 ` Ard Biesheuvel
2016-12-02 15:56 ` Leif Lindholm
0 siblings, 1 reply; 19+ messages in thread
From: Ard Biesheuvel @ 2016-12-02 15:07 UTC (permalink / raw)
To: Leif Lindholm
Cc: Ni, Ruiyu, edk2-devel@lists.01.org, Gao, Liming, afish@apple.com,
Kinney, Michael D, mw@semihalf.com, Tian, Feng
> On 2 Dec 2016, at 14:40, Leif Lindholm <leif.lindholm@linaro.org> wrote:
>
> On Fri, Dec 02, 2016 at 12:54:45PM +0000, Ni, Ruiyu wrote:
>>>>> + Dev->ConfigSpace.Device.Bar[Idx] = (UINT32)Desc->AddrRangeMin;
>>>>> + Dev->BarCount++;
>>>>> +
>>>>> + if (Desc->AddrSpaceGranularity == 64) {
>>>>> + Dev->ConfigSpace.Device.Bar[Idx] |= 0x4;
>>>>> + Dev->ConfigSpace.Device.Bar[++Idx] = (UINT32)(Desc->AddrRangeMin >> 32);
>>>>
>>>> 1. You need to use RShiftU64 otherwise the above code will break the
>>>> build process in 32bit.
>>>
>>> I don't understand how that could cause breakage (and experiments with
>>> IA32 and ARM fail to reproduce it with GCC).
>>>
>>> - Bar[x] is an array of UINT32
>>> - Desc->AddrRangeMin is UINT64
>>> - The result of (Desc->AddrRangeMin >> 32) is explicitly cast to
>>> UINT32 (the type of Bar[x]).
>>>
>>> Is the problem related to the shift value being signed?
>>> Or does some other compiler refuse to cast a UINT64 to a UINT32?
>>
>> Desc->AddrRangeMin is UINT64. My experience tells me that
>> LShiftU64 or RShiftU64 should be used for shifting operation
>> on UINT64.
>
> This is the bit that confuses me. There is no such automatic
> limitation in the C language (if long long is supported at all). So if
> we're working around some bug in a specific compiler - I am happy to
> do so. I just prefer knowing why rather than cargo-culting.
>
>> I guess the GCC might cleverly recognizes the ">>32" actually
>> picks up the high-32 bits so in 32bit environment, it just uses
>> value of the register which stores the high-32 bits.
>> Can you check the assembly code GCC generates?
>> or simply can you change ">>32" to ">>31" or ">>33" to see
>> what happens?
>
> There is no cleverness required, it's just a defined operation on a
> base type. But sure, for example:
>
> unsigned int shift(long long val)
> {
> return (val >> 33);
> }
>
> decodes as
> ---
> 0000000000000000 <shift>:
> 0: 48 89 f8 mov %rdi,%rax
> 3: 48 c1 f8 21 sar $0x21,%rax
> 7: c3 retq
> ---
> (in x86_64, using gcc -O2 to get rid of some redundant stack
> operations)
>
> The only thing that changes if the shift value is modified is that the
> 0x21 is changed accordingly.
>
> Change it to an inline constant, not much changes:
>
> unsigned int shiftconst(void)
> {
> unsigned long long var = 0xaaaabbbbccccddddULL;
> return (var >> 31);
> }
>
> decodes as
> ---
> 0000000000000000 <shiftconst>:
> 0: 55 push %rbp
> 1: 48 89 e5 mov %rsp,%rbp
> 4: 48 b8 dd dd cc cc bb movabs $0xaaaabbbbccccdddd,%rax
> b: bb aa aa
> e: 48 89 45 f8 mov %rax,-0x8(%rbp)
> 12: 48 8b 45 f8 mov -0x8(%rbp),%rax
> 16: 48 c1 e8 1f shr $0x1f,%rax
> 1a: 5d pop %rbp
> 1b: c3 retq
> ---
> (with -O0, to prevent the compiler from just doing the arithmetic
> compile time)
>
> Both also compile correctly for IA32 with -m32.
>
> The point is that there is nothing clever here for the compiler to do:
> casting a 64-bit int to a 32-bit int is an operation that discards the
> top 32 bits - but the behaviour is entirely defined.
>
> In fact, all architectures other than IA32/ARM use the Math64.c
> implementation of RShiftU64, which simply does the shift.
> And ARM does it only for GCC. I'm not sure why, I can't imagine a GCC
> version that would do anything more complicated than
> ---
> 00000000 <shift>:
> 0: e1a000c1 asr r0, r1, #1
> 4: e12fff1e bx lr
> ---
> (and that's with -march=armv4t onwards)
That's a 32-bit operand. Shifting a 64-bit value will result in a call to a compiler intrinsic, which is kind of the point of Riuyu's remark
> So if we are saying that there are certain specific compilers that do
> not support 64-bit arithmetic for 32-bit architectures, and that those
> compilers are still supported by BaseTools - then I'm fine with that.
>
> But I don't want to replace functional C code with abstraction
> functions without a proper understanding of where it would be
> problematic.
>
> Regards,
>
> Leif
>
>>
>>>
>>> Regards,
>>>
>>> Leif
>>>
>>>>> + }
>>>>> + }
>>>>> +}
>>>>> diff --git
>>>>> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>>>>> PciDeviceIo.h
>>>>> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>>>>> PciDeviceIo.h
>>>>> new file mode 100644
>>>>> index 000000000000..bc0a3d3258f9
>>>>> --- /dev/null
>>>>> +++
>>>>> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>>>>> Pc
>>>>> +++ iDeviceIo.h
>>>>> @@ -0,0 +1,84 @@
>>>>> +/** @file
>>>>> +
>>>>> + Copyright (C) 2016, Linaro Ltd. 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
>>>>> +
>>>>> + 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 __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
>>>>> +#define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
>>>>> +
>>>>> +#include <Library/BaseMemoryLib.h>
>>>>> +#include <Library/DebugLib.h>
>>>>> +#include <Library/MemoryAllocationLib.h> #include
>>>>> +<Library/UefiBootServicesTableLib.h>
>>>>> +#include <Library/UefiLib.h>
>>>>> +
>>>>> +#include <IndustryStandard/Pci.h>
>>>>> +
>>>>> +#include <Protocol/ComponentName.h>
>>>>> +#include <Protocol/NonDiscoverableDevice.h>
>>>>> +#include <Protocol/PciIo.h>
>>>>> +
>>>>> +#define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I',
>>>>> +'D')
>>>>> +
>>>>> +#define NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(PciIoPointer) \
>>>>> + CR (PciIoPointer, NON_DISCOVERABLE_PCI_DEVICE, PciIo, \
>>>>> + NON_DISCOVERABLE_PCI_DEVICE_SIG)
>>>>> +
>>>>> +#define PCI_ID_VENDOR_UNKNOWN 0xffff
>>>>> +#define PCI_ID_DEVICE_DONTCARE 0x0000
>>>>> +
>>>>> +#define PCI_MAX_BARS 6
>>>>> +
>>>>> +typedef struct {
>>>>> + UINT32 Signature;
>>>>> + //
>>>>> + // The bound non-discoverable device protocol instance
>>>>> + //
>>>>> + NON_DISCOVERABLE_DEVICE *Device;
>>>>> + //
>>>>> + // The exposed PCI I/O protocol instance.
>>>>> + //
>>>>> + EFI_PCI_IO_PROTOCOL PciIo;
>>>>> + //
>>>>> + // The emulated PCI config space of the device. Only the minimally
>>>>> +required
>>>>> + // items are assigned.
>>>>> + //
>>>>> + PCI_TYPE00 ConfigSpace;
>>>>> + //
>>>>> + // The first virtual BAR to assign based on the resources described
>>>>> + // by the non-discoverable device.
>>>>> + //
>>>>> + UINT32 BarOffset;
>>>>> + //
>>>>> + // The number of virtual BARs we expose based on the number of
>>>>> + // resources
>>>>> + //
>>>>> + UINT32 BarCount;
>>>>> + //
>>>>> + // The PCI I/O attributes for this device
>>>>> + //
>>>>> + UINT64 Attributes;
>>>>> + //
>>>>> + // Whether this device has been enabled
>>>>> + //
>>>>> + BOOLEAN Enabled;
>>>>> +} NON_DISCOVERABLE_PCI_DEVICE;
>>>>> +
>>>>> +VOID
>>>>> +InitializePciIoProtocol (
>>>>> + NON_DISCOVERABLE_PCI_DEVICE *Device
>>>>> + );
>>>>> +
>>>>> +extern EFI_COMPONENT_NAME_PROTOCOL gComponentName; extern
>>>>> +EFI_COMPONENT_NAME2_PROTOCOL gComponentName2;
>>>>> +
>>>>> +#endif
>>>>> diff --git a/MdeModulePkg/MdeModulePkg.dsc
>>>>> b/MdeModulePkg/MdeModulePkg.dsc index 20e5e8c78be0..5dd30556cb3c
>>>>> 100644
>>>>> --- a/MdeModulePkg/MdeModulePkg.dsc
>>>>> +++ b/MdeModulePkg/MdeModulePkg.dsc
>>>>> @@ -265,6 +265,7 @@ [Components]
>>>>> MdeModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf
>>>>> MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
>>>>> MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
>>>>> +
>>>>> +
>>>>> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
>>>>> Dev
>>>>> + iceDxe.inf
>>>>>
>>>>> MdeModulePkg/Core/Dxe/DxeMain.inf {
>>>>> <LibraryClasses>
>>>>> --
>>>>> 2.7.4
>>>>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4 3/5] MdeModulePkg: implement generic PCI I/O driver for non-discoverable devices
2016-12-02 15:07 ` Ard Biesheuvel
@ 2016-12-02 15:56 ` Leif Lindholm
2016-12-02 18:42 ` Ard Biesheuvel
0 siblings, 1 reply; 19+ messages in thread
From: Leif Lindholm @ 2016-12-02 15:56 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Ni, Ruiyu, edk2-devel@lists.01.org, Gao, Liming, afish@apple.com,
Kinney, Michael D, mw@semihalf.com, Tian, Feng
On Fri, Dec 02, 2016 at 03:07:39PM +0000, Ard Biesheuvel wrote:
>
> > On 2 Dec 2016, at 14:40, Leif Lindholm <leif.lindholm@linaro.org> wrote:
> >
> > On Fri, Dec 02, 2016 at 12:54:45PM +0000, Ni, Ruiyu wrote:
> >>>>> + Dev->ConfigSpace.Device.Bar[Idx] = (UINT32)Desc->AddrRangeMin;
> >>>>> + Dev->BarCount++;
> >>>>> +
> >>>>> + if (Desc->AddrSpaceGranularity == 64) {
> >>>>> + Dev->ConfigSpace.Device.Bar[Idx] |= 0x4;
> >>>>> + Dev->ConfigSpace.Device.Bar[++Idx] = (UINT32)(Desc->AddrRangeMin >> 32);
> >>>>
> >>>> 1. You need to use RShiftU64 otherwise the above code will break the
> >>>> build process in 32bit.
> >>>
> >>> I don't understand how that could cause breakage (and experiments with
> >>> IA32 and ARM fail to reproduce it with GCC).
> >>>
> >>> - Bar[x] is an array of UINT32
> >>> - Desc->AddrRangeMin is UINT64
> >>> - The result of (Desc->AddrRangeMin >> 32) is explicitly cast to
> >>> UINT32 (the type of Bar[x]).
> >>>
> >>> Is the problem related to the shift value being signed?
> >>> Or does some other compiler refuse to cast a UINT64 to a UINT32?
> >>
> >> Desc->AddrRangeMin is UINT64. My experience tells me that
> >> LShiftU64 or RShiftU64 should be used for shifting operation
> >> on UINT64.
> >
> > This is the bit that confuses me. There is no such automatic
> > limitation in the C language (if long long is supported at all). So if
> > we're working around some bug in a specific compiler - I am happy to
> > do so. I just prefer knowing why rather than cargo-culting.
> >
> >> I guess the GCC might cleverly recognizes the ">>32" actually
> >> picks up the high-32 bits so in 32bit environment, it just uses
> >> value of the register which stores the high-32 bits.
> >> Can you check the assembly code GCC generates?
> >> or simply can you change ">>32" to ">>31" or ">>33" to see
> >> what happens?
> >
> > There is no cleverness required, it's just a defined operation on a
> > base type. But sure, for example:
> >
> > unsigned int shift(long long val)
> > {
> > return (val >> 33);
> > }
> >
> > decodes as
> > ---
> > 0000000000000000 <shift>:
> > 0: 48 89 f8 mov %rdi,%rax
> > 3: 48 c1 f8 21 sar $0x21,%rax
> > 7: c3 retq
> > ---
> > (in x86_64, using gcc -O2 to get rid of some redundant stack
> > operations)
> >
> > The only thing that changes if the shift value is modified is that the
> > 0x21 is changed accordingly.
> >
> > Change it to an inline constant, not much changes:
> >
> > unsigned int shiftconst(void)
> > {
> > unsigned long long var = 0xaaaabbbbccccddddULL;
> > return (var >> 31);
> > }
> >
> > decodes as
> > ---
> > 0000000000000000 <shiftconst>:
> > 0: 55 push %rbp
> > 1: 48 89 e5 mov %rsp,%rbp
> > 4: 48 b8 dd dd cc cc bb movabs $0xaaaabbbbccccdddd,%rax
> > b: bb aa aa
> > e: 48 89 45 f8 mov %rax,-0x8(%rbp)
> > 12: 48 8b 45 f8 mov -0x8(%rbp),%rax
> > 16: 48 c1 e8 1f shr $0x1f,%rax
> > 1a: 5d pop %rbp
> > 1b: c3 retq
> > ---
> > (with -O0, to prevent the compiler from just doing the arithmetic
> > compile time)
> >
> > Both also compile correctly for IA32 with -m32.
> >
> > The point is that there is nothing clever here for the compiler to do:
> > casting a 64-bit int to a 32-bit int is an operation that discards the
> > top 32 bits - but the behaviour is entirely defined.
> >
> > In fact, all architectures other than IA32/ARM use the Math64.c
> > implementation of RShiftU64, which simply does the shift.
> > And ARM does it only for GCC. I'm not sure why, I can't imagine a GCC
> > version that would do anything more complicated than
> > ---
> > 00000000 <shift>:
> > 0: e1a000c1 asr r0, r1, #1
> > 4: e12fff1e bx lr
> > ---
> > (and that's with -march=armv4t onwards)
>
> That's a 32-bit operand. Shifting a 64-bit value will result in a
> call to a compiler intrinsic, which is kind of the point of Riuyu's
> remark
No, it's not.
As stated, that is the output from compiling:
unsigned int shift(long long val)
{
return (val >> 33);
}
Unless you are claiming long long is 32-bit on ARM.
Although I did mess up and make it signed :)
When fixed, the code generation is identical but with an lsr instead.
The compiler just operates directly on the top 32-bits (in r1), since
the ones in r0 are irrelevant to the result.
Change the shift to 31 and the compiler doesn't do anything cute, so
the code is slightly more obvious:
---
00000000 <shift>:
0: e1a00fa0 lsr r0, r0, #31
4: e1800081 orr r0, r0, r1, lsl #1
8: e12fff1e bx lr
---
But even if there were intrinsics generated, shouldn't we support the
intrinsic instead of massaging the C code and hope we can prevent it
from being generated.
/
Leif
>
>
> > So if we are saying that there are certain specific compilers that do
> > not support 64-bit arithmetic for 32-bit architectures, and that those
> > compilers are still supported by BaseTools - then I'm fine with that.
> >
> > But I don't want to replace functional C code with abstraction
> > functions without a proper understanding of where it would be
> > problematic.
> >
> > Regards,
> >
> > Leif
> >
> >>
> >>>
> >>> Regards,
> >>>
> >>> Leif
> >>>
> >>>>> + }
> >>>>> + }
> >>>>> +}
> >>>>> diff --git
> >>>>> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> >>>>> PciDeviceIo.h
> >>>>> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> >>>>> PciDeviceIo.h
> >>>>> new file mode 100644
> >>>>> index 000000000000..bc0a3d3258f9
> >>>>> --- /dev/null
> >>>>> +++
> >>>>> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> >>>>> Pc
> >>>>> +++ iDeviceIo.h
> >>>>> @@ -0,0 +1,84 @@
> >>>>> +/** @file
> >>>>> +
> >>>>> + Copyright (C) 2016, Linaro Ltd. 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
> >>>>> +
> >>>>> + 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 __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
> >>>>> +#define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
> >>>>> +
> >>>>> +#include <Library/BaseMemoryLib.h>
> >>>>> +#include <Library/DebugLib.h>
> >>>>> +#include <Library/MemoryAllocationLib.h> #include
> >>>>> +<Library/UefiBootServicesTableLib.h>
> >>>>> +#include <Library/UefiLib.h>
> >>>>> +
> >>>>> +#include <IndustryStandard/Pci.h>
> >>>>> +
> >>>>> +#include <Protocol/ComponentName.h>
> >>>>> +#include <Protocol/NonDiscoverableDevice.h>
> >>>>> +#include <Protocol/PciIo.h>
> >>>>> +
> >>>>> +#define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I',
> >>>>> +'D')
> >>>>> +
> >>>>> +#define NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(PciIoPointer) \
> >>>>> + CR (PciIoPointer, NON_DISCOVERABLE_PCI_DEVICE, PciIo, \
> >>>>> + NON_DISCOVERABLE_PCI_DEVICE_SIG)
> >>>>> +
> >>>>> +#define PCI_ID_VENDOR_UNKNOWN 0xffff
> >>>>> +#define PCI_ID_DEVICE_DONTCARE 0x0000
> >>>>> +
> >>>>> +#define PCI_MAX_BARS 6
> >>>>> +
> >>>>> +typedef struct {
> >>>>> + UINT32 Signature;
> >>>>> + //
> >>>>> + // The bound non-discoverable device protocol instance
> >>>>> + //
> >>>>> + NON_DISCOVERABLE_DEVICE *Device;
> >>>>> + //
> >>>>> + // The exposed PCI I/O protocol instance.
> >>>>> + //
> >>>>> + EFI_PCI_IO_PROTOCOL PciIo;
> >>>>> + //
> >>>>> + // The emulated PCI config space of the device. Only the minimally
> >>>>> +required
> >>>>> + // items are assigned.
> >>>>> + //
> >>>>> + PCI_TYPE00 ConfigSpace;
> >>>>> + //
> >>>>> + // The first virtual BAR to assign based on the resources described
> >>>>> + // by the non-discoverable device.
> >>>>> + //
> >>>>> + UINT32 BarOffset;
> >>>>> + //
> >>>>> + // The number of virtual BARs we expose based on the number of
> >>>>> + // resources
> >>>>> + //
> >>>>> + UINT32 BarCount;
> >>>>> + //
> >>>>> + // The PCI I/O attributes for this device
> >>>>> + //
> >>>>> + UINT64 Attributes;
> >>>>> + //
> >>>>> + // Whether this device has been enabled
> >>>>> + //
> >>>>> + BOOLEAN Enabled;
> >>>>> +} NON_DISCOVERABLE_PCI_DEVICE;
> >>>>> +
> >>>>> +VOID
> >>>>> +InitializePciIoProtocol (
> >>>>> + NON_DISCOVERABLE_PCI_DEVICE *Device
> >>>>> + );
> >>>>> +
> >>>>> +extern EFI_COMPONENT_NAME_PROTOCOL gComponentName; extern
> >>>>> +EFI_COMPONENT_NAME2_PROTOCOL gComponentName2;
> >>>>> +
> >>>>> +#endif
> >>>>> diff --git a/MdeModulePkg/MdeModulePkg.dsc
> >>>>> b/MdeModulePkg/MdeModulePkg.dsc index 20e5e8c78be0..5dd30556cb3c
> >>>>> 100644
> >>>>> --- a/MdeModulePkg/MdeModulePkg.dsc
> >>>>> +++ b/MdeModulePkg/MdeModulePkg.dsc
> >>>>> @@ -265,6 +265,7 @@ [Components]
> >>>>> MdeModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf
> >>>>> MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
> >>>>> MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
> >>>>> +
> >>>>> +
> >>>>> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
> >>>>> Dev
> >>>>> + iceDxe.inf
> >>>>>
> >>>>> MdeModulePkg/Core/Dxe/DxeMain.inf {
> >>>>> <LibraryClasses>
> >>>>> --
> >>>>> 2.7.4
> >>>>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4 3/5] MdeModulePkg: implement generic PCI I/O driver for non-discoverable devices
2016-12-02 15:56 ` Leif Lindholm
@ 2016-12-02 18:42 ` Ard Biesheuvel
2016-12-05 9:35 ` Leif Lindholm
0 siblings, 1 reply; 19+ messages in thread
From: Ard Biesheuvel @ 2016-12-02 18:42 UTC (permalink / raw)
To: Leif Lindholm
Cc: Ni, Ruiyu, Tian, Feng, edk2-devel@lists.01.org, afish@apple.com,
Gao, Liming, Kinney, Michael D
On 2 December 2016 at 15:56, Leif Lindholm <leif.lindholm@linaro.org> wrote:
> On Fri, Dec 02, 2016 at 03:07:39PM +0000, Ard Biesheuvel wrote:
>>
>> > On 2 Dec 2016, at 14:40, Leif Lindholm <leif.lindholm@linaro.org> wrote:
>> >
>> > On Fri, Dec 02, 2016 at 12:54:45PM +0000, Ni, Ruiyu wrote:
>> >>>>> + Dev->ConfigSpace.Device.Bar[Idx] = (UINT32)Desc->AddrRangeMin;
>> >>>>> + Dev->BarCount++;
>> >>>>> +
>> >>>>> + if (Desc->AddrSpaceGranularity == 64) {
>> >>>>> + Dev->ConfigSpace.Device.Bar[Idx] |= 0x4;
>> >>>>> + Dev->ConfigSpace.Device.Bar[++Idx] = (UINT32)(Desc->AddrRangeMin >> 32);
>> >>>>
>> >>>> 1. You need to use RShiftU64 otherwise the above code will break the
>> >>>> build process in 32bit.
>> >>>
>> >>> I don't understand how that could cause breakage (and experiments with
>> >>> IA32 and ARM fail to reproduce it with GCC).
>> >>>
>> >>> - Bar[x] is an array of UINT32
>> >>> - Desc->AddrRangeMin is UINT64
>> >>> - The result of (Desc->AddrRangeMin >> 32) is explicitly cast to
>> >>> UINT32 (the type of Bar[x]).
>> >>>
>> >>> Is the problem related to the shift value being signed?
>> >>> Or does some other compiler refuse to cast a UINT64 to a UINT32?
>> >>
>> >> Desc->AddrRangeMin is UINT64. My experience tells me that
>> >> LShiftU64 or RShiftU64 should be used for shifting operation
>> >> on UINT64.
>> >
>> > This is the bit that confuses me. There is no such automatic
>> > limitation in the C language (if long long is supported at all). So if
>> > we're working around some bug in a specific compiler - I am happy to
>> > do so. I just prefer knowing why rather than cargo-culting.
>> >
>> >> I guess the GCC might cleverly recognizes the ">>32" actually
>> >> picks up the high-32 bits so in 32bit environment, it just uses
>> >> value of the register which stores the high-32 bits.
>> >> Can you check the assembly code GCC generates?
>> >> or simply can you change ">>32" to ">>31" or ">>33" to see
>> >> what happens?
>> >
>> > There is no cleverness required, it's just a defined operation on a
>> > base type. But sure, for example:
>> >
>> > unsigned int shift(long long val)
>> > {
>> > return (val >> 33);
>> > }
>> >
>> > decodes as
>> > ---
>> > 0000000000000000 <shift>:
>> > 0: 48 89 f8 mov %rdi,%rax
>> > 3: 48 c1 f8 21 sar $0x21,%rax
>> > 7: c3 retq
>> > ---
>> > (in x86_64, using gcc -O2 to get rid of some redundant stack
>> > operations)
>> >
>> > The only thing that changes if the shift value is modified is that the
>> > 0x21 is changed accordingly.
>> >
>> > Change it to an inline constant, not much changes:
>> >
>> > unsigned int shiftconst(void)
>> > {
>> > unsigned long long var = 0xaaaabbbbccccddddULL;
>> > return (var >> 31);
>> > }
>> >
>> > decodes as
>> > ---
>> > 0000000000000000 <shiftconst>:
>> > 0: 55 push %rbp
>> > 1: 48 89 e5 mov %rsp,%rbp
>> > 4: 48 b8 dd dd cc cc bb movabs $0xaaaabbbbccccdddd,%rax
>> > b: bb aa aa
>> > e: 48 89 45 f8 mov %rax,-0x8(%rbp)
>> > 12: 48 8b 45 f8 mov -0x8(%rbp),%rax
>> > 16: 48 c1 e8 1f shr $0x1f,%rax
>> > 1a: 5d pop %rbp
>> > 1b: c3 retq
>> > ---
>> > (with -O0, to prevent the compiler from just doing the arithmetic
>> > compile time)
>> >
>> > Both also compile correctly for IA32 with -m32.
>> >
>> > The point is that there is nothing clever here for the compiler to do:
>> > casting a 64-bit int to a 32-bit int is an operation that discards the
>> > top 32 bits - but the behaviour is entirely defined.
>> >
>> > In fact, all architectures other than IA32/ARM use the Math64.c
>> > implementation of RShiftU64, which simply does the shift.
>> > And ARM does it only for GCC. I'm not sure why, I can't imagine a GCC
>> > version that would do anything more complicated than
>> > ---
>> > 00000000 <shift>:
>> > 0: e1a000c1 asr r0, r1, #1
>> > 4: e12fff1e bx lr
>> > ---
>> > (and that's with -march=armv4t onwards)
>>
>> That's a 32-bit operand. Shifting a 64-bit value will result in a
>> call to a compiler intrinsic, which is kind of the point of Riuyu's
>> remark
>
> No, it's not.
> As stated, that is the output from compiling:
>
> unsigned int shift(long long val)
> {
> return (val >> 33);
> }
>
> Unless you are claiming long long is 32-bit on ARM.
>
> Although I did mess up and make it signed :)
> When fixed, the code generation is identical but with an lsr instead.
>
> The compiler just operates directly on the top 32-bits (in r1), since
> the ones in r0 are irrelevant to the result.
>
OK, but that does mean it is performing optimization up to some point.
So right shifts of 64-bit quantities by 32 bits or more will be
'optimized' by GCC into something that does not rely on the
intrinsics. But this is not universally true for all toolchains (and
variable shifts are probably treated differently as well)
> Change the shift to 31 and the compiler doesn't do anything cute, so
> the code is slightly more obvious:
> ---
> 00000000 <shift>:
> 0: e1a00fa0 lsr r0, r0, #31
> 4: e1800081 orr r0, r0, r1, lsl #1
> 8: e12fff1e bx lr
> ---
>
> But even if there were intrinsics generated, shouldn't we support the
> intrinsic instead of massaging the C code and hope we can prevent it
> from being generated.
>
This is exactly the issue at hand: EDK2 typically does *not* rely on
such intrinsics, even if we were forced to add them for ARM because
GCC cannot be instructed to inhibit such calls.
Actually, I do not agree with the EDK2 position, i.e., I think there
is no issue relying on routines that are typically provided by the C
runtime. But this is MdeModulePkg, so it is not up to us.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4 3/5] MdeModulePkg: implement generic PCI I/O driver for non-discoverable devices
2016-12-02 18:42 ` Ard Biesheuvel
@ 2016-12-05 9:35 ` Leif Lindholm
0 siblings, 0 replies; 19+ messages in thread
From: Leif Lindholm @ 2016-12-05 9:35 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Ni, Ruiyu, Tian, Feng, edk2-devel@lists.01.org, afish@apple.com,
Gao, Liming, Kinney, Michael D
On Fri, Dec 02, 2016 at 06:42:58PM +0000, Ard Biesheuvel wrote:
> >> > The point is that there is nothing clever here for the compiler to do:
> >> > casting a 64-bit int to a 32-bit int is an operation that discards the
> >> > top 32 bits - but the behaviour is entirely defined.
> >> >
> >> > In fact, all architectures other than IA32/ARM use the Math64.c
> >> > implementation of RShiftU64, which simply does the shift.
> >> > And ARM does it only for GCC. I'm not sure why, I can't imagine a GCC
> >> > version that would do anything more complicated than
> >> > ---
> >> > 00000000 <shift>:
> >> > 0: e1a000c1 asr r0, r1, #1
> >> > 4: e12fff1e bx lr
> >> > ---
> >> > (and that's with -march=armv4t onwards)
> >>
> >> That's a 32-bit operand. Shifting a 64-bit value will result in a
> >> call to a compiler intrinsic, which is kind of the point of Riuyu's
> >> remark
> >
> > No, it's not.
> > As stated, that is the output from compiling:
> >
> > unsigned int shift(long long val)
> > {
> > return (val >> 33);
> > }
> >
> > Unless you are claiming long long is 32-bit on ARM.
> >
> > Although I did mess up and make it signed :)
> > When fixed, the code generation is identical but with an lsr instead.
> >
> > The compiler just operates directly on the top 32-bits (in r1), since
> > the ones in r0 are irrelevant to the result.
>
> OK, but that does mean it is performing optimization up to some point.
> So right shifts of 64-bit quantities by 32 bits or more will be
> 'optimized' by GCC into something that does not rely on the
> intrinsics. But this is not universally true for all toolchains
And I'm OK with a statement of "we can't do this because version X of
toolchain Y does not support it". But I am much less happy for people
to introduce workarounds in functional code because of an issue that
may no longer be relevant for any toolchains actually in use (or even
supported by BaseTools).
At which point can we know this problem goes away and we can program
in regular C instead, if we decide to obsolete some extremely outdated
toolchains?
> (and variable shifts are probably treated differently as well)
It has no effect on intrinsics being required or not, it simply requires
some more stack shuffling. But yes, that removes all options for
compiler shortcuts.
> > Change the shift to 31 and the compiler doesn't do anything cute, so
> > the code is slightly more obvious:
> > ---
> > 00000000 <shift>:
> > 0: e1a00fa0 lsr r0, r0, #31
> > 4: e1800081 orr r0, r0, r1, lsl #1
> > 8: e12fff1e bx lr
> > ---
> >
> > But even if there were intrinsics generated, shouldn't we support the
> > intrinsic instead of massaging the C code and hope we can prevent it
> > from being generated.
>
> This is exactly the issue at hand: EDK2 typically does *not* rely on
> such intrinsics, even if we were forced to add them for ARM because
> GCC cannot be instructed to inhibit such calls.
>
> Actually, I do not agree with the EDK2 position, i.e., I think there
> is no issue relying on routines that are typically provided by the C
> runtime. But this is MdeModulePkg, so it is not up to us.
Indeed it is not.
But this does not sound like a topic we want per-package rules on.
Regards,
Leif
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2016-12-05 9:35 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-11-25 15:42 [PATCH v4 0/5] MdeModulePkg: add support for non-discoverable devices Ard Biesheuvel
2016-11-25 15:42 ` [PATCH v4 1/5] MdeModulePkg: introduce non-discoverable device protocol Ard Biesheuvel
2016-11-28 1:57 ` Ni, Ruiyu
2016-11-25 15:42 ` [PATCH v4 2/5] MdeModulePkg: introduce helper library to register non-discoverable devices Ard Biesheuvel
2016-11-28 1:58 ` Ni, Ruiyu
2016-11-25 15:42 ` [PATCH v4 3/5] MdeModulePkg: implement generic PCI I/O driver for " Ard Biesheuvel
2016-11-28 1:56 ` Ni, Ruiyu
2016-11-30 14:06 ` Leif Lindholm
2016-12-02 10:09 ` Leif Lindholm
2016-12-02 12:54 ` Ni, Ruiyu
2016-12-02 14:40 ` Leif Lindholm
2016-12-02 15:07 ` Ard Biesheuvel
2016-12-02 15:56 ` Leif Lindholm
2016-12-02 18:42 ` Ard Biesheuvel
2016-12-05 9:35 ` Leif Lindholm
2016-11-25 15:42 ` [PATCH v4 4/5] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Ard Biesheuvel
2016-11-28 2:25 ` Ni, Ruiyu
2016-11-25 15:42 ` [PATCH v4 5/5] Omap35xxPkg/PciEmulation: port to new non-discoverable device infrastructure Ard Biesheuvel
2016-11-27 10:18 ` [PATCH v4 0/5] MdeModulePkg: add support for non-discoverable devices Marcin Wojtas
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox