summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/configs/efi_defconfig1
-rw-r--r--arch/x86/include/asm/pci.h7
-rw-r--r--drivers/efi/Kconfig1
-rw-r--r--drivers/pci/Kconfig5
-rw-r--r--drivers/pci/Makefile1
-rw-r--r--drivers/pci/pci-efi.c342
-rw-r--r--drivers/pci/pci-efi.h343
7 files changed, 700 insertions, 0 deletions
diff --git a/arch/x86/configs/efi_defconfig b/arch/x86/configs/efi_defconfig
index 761ffbe261..e007bf8a01 100644
--- a/arch/x86/configs/efi_defconfig
+++ b/arch/x86/configs/efi_defconfig
@@ -88,6 +88,7 @@ CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_EFI=y
CONFIG_F71808E_WDT=y
# CONFIG_PINCTRL is not set
+CONFIG_PCI_EFI=y
CONFIG_FS_EXT4=y
CONFIG_FS_TFTP=y
CONFIG_FS_NFS=y
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
new file mode 100644
index 0000000000..ca1c0f912d
--- /dev/null
+++ b/arch/x86/include/asm/pci.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_PCI_H
+#define __ASM_PCI_H
+
+#define pcibios_assign_all_busses() 0
+
+#endif
diff --git a/drivers/efi/Kconfig b/drivers/efi/Kconfig
index cca1a2e1d6..80d9e6f0c5 100644
--- a/drivers/efi/Kconfig
+++ b/drivers/efi/Kconfig
@@ -2,3 +2,4 @@ config EFI_BOOTUP
bool
select BLOCK
select PARTITION_DISK
+ select HW_HAS_PCI
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 0585460976..71d05055d4 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -54,6 +54,11 @@ config PCI_LAYERSCAPE
select OF_PCI
select PCI
+config PCI_EFI
+ bool "EFI PCI protocol"
+ depends on EFI_BOOTUP
+ select PCI
+
endmenu
endif
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index d227619ed4..6fc4eaf6b2 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
obj-$(CONFIG_PCIE_DW) += pcie-designware.o pcie-designware-host.o
obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
+obj-$(CONFIG_PCI_EFI) += pci-efi.o
diff --git a/drivers/pci/pci-efi.c b/drivers/pci/pci-efi.c
new file mode 100644
index 0000000000..e1fe11d070
--- /dev/null
+++ b/drivers/pci/pci-efi.c
@@ -0,0 +1,342 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 Ahmad Fatoum <a.fatoum@pengutronix.de>
+ */
+#define pr_fmt(fmt) "pci-efi: " fmt
+
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <xfuncs.h>
+#include <efi.h>
+#include <efi/efi.h>
+#include <efi/efi-device.h>
+#include <linux/pci.h>
+
+#include "pci-efi.h"
+
+struct efi_pci_priv {
+ struct efi_pci_root_bridge_io_protocol *protocol;
+ struct device_d *dev;
+ struct pci_controller pci;
+ struct resource mem;
+ struct resource mem_pref;
+ struct resource io;
+ struct list_head children;
+};
+
+struct pci_child_id {
+ size_t segmentno;
+ size_t busno;
+ size_t devno;
+ size_t funcno;
+};
+
+struct pci_child {
+ struct efi_pci_io_protocol *protocol;
+ struct device_d *dev;
+ struct list_head list;
+ struct pci_child_id id;
+};
+
+static inline bool pci_child_id_equal(struct pci_child_id *a, struct pci_child_id *b)
+{
+ return a->segmentno == b->segmentno
+ && a->busno == b->busno
+ && a->devno == b->devno
+ && a->funcno == b->funcno;
+}
+
+#define host_to_efi_pci(host) container_of(host, struct efi_pci_priv, pci)
+
+static inline u64 efi_pci_addr(struct pci_bus *bus, u32 devfn, int where)
+{
+ return EFI_PCI_ADDRESS(bus->number,
+ PCI_SLOT(devfn), PCI_FUNC(devfn),
+ where);
+}
+
+static int efi_pci_rd_conf(struct pci_bus *bus, u32 devfn, int where,
+ int size, u32 *val)
+{
+ struct efi_pci_priv *priv = host_to_efi_pci(bus->host);
+ efi_status_t efiret;
+ u32 value;
+ enum efi_pci_protocol_width width;
+
+ switch (size) {
+ case 4:
+ width = EFI_PCI_WIDTH_U32;
+ break;
+ case 2:
+ width = EFI_PCI_WIDTH_U16;
+ break;
+ case 1:
+ width = EFI_PCI_WIDTH_U8;
+ break;
+ default:
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ }
+
+ efiret = priv->protocol->pci.read(priv->protocol, width,
+ efi_pci_addr(bus, devfn, where),
+ 1, &value);
+
+ *val = 0xFFFFFFFF;
+
+ if (EFI_ERROR(efiret))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ *val = value;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int efi_pci_wr_conf(struct pci_bus *bus, u32 devfn, int where,
+ int size, u32 val)
+{
+ struct efi_pci_priv *priv = host_to_efi_pci(bus->host);
+ efi_status_t efiret;
+ enum efi_pci_protocol_width width;
+
+ switch (size) {
+ case 4:
+ width = EFI_PCI_WIDTH_U32;
+ break;
+ case 2:
+ width = EFI_PCI_WIDTH_U16;
+ break;
+ case 1:
+ width = EFI_PCI_WIDTH_U8;
+ break;
+ default:
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ }
+
+ efiret = priv->protocol->pci.write(priv->protocol, width,
+ efi_pci_addr(bus, devfn, where),
+ 1, &val);
+ if (EFI_ERROR(efiret))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static inline struct resource build_resource(const char *name,
+ resource_size_t start,
+ resource_size_t len,
+ unsigned long flags)
+{
+ struct resource res;
+
+ res.name = name;
+ res.start = start;
+ res.end = start + len - 1;
+ res.flags = flags;
+ res.parent = NULL;
+ INIT_LIST_HEAD(&res.children);
+ INIT_LIST_HEAD(&res.sibling);
+
+ return res;
+}
+
+static const struct pci_ops efi_pci_ops = {
+ .read = efi_pci_rd_conf,
+ .write = efi_pci_wr_conf,
+};
+
+static u8 *acpi_parse_resource(u8 *next, struct resource *out)
+{
+ struct efi_acpi_resource *res;
+ const char *name = NULL;
+ unsigned long flags = 0;
+
+ do {
+ if (*next == ACPI_RESOURCE_END_TAG)
+ return NULL;
+
+ if (*next != ACPI_RESOURCE_DESC_TAG)
+ return ERR_PTR(-EIO);
+
+ res = container_of(next, struct efi_acpi_resource, asd);
+
+ next = (u8 *)&res[1];
+ } while (res->addr_len == 0);
+
+ switch (res->restype) {
+ case ACPI_RESOURCE_TYPE_MEM:
+ if ((res->typflags & ACPI_RESOURCE_TYPFLAG_MTP_MASK)
+ != ACPI_RESOURCE_TYPFLAG_MTP_MEM)
+ break;
+
+ name = "NP-MEM";
+ flags = IORESOURCE_MEM;
+
+ switch (res->typflags & ACPI_RESOURCE_TYPFLAG_MEM_MASK) {
+ case ACPI_RESOURCE_TYPFLAG_MEM_PREF:
+ name = "P-MEM";
+ flags |= IORESOURCE_PREFETCH;
+ /* fallthrough */
+ case ACPI_RESOURCE_TYPFLAG_MEM_WC:
+ case ACPI_RESOURCE_TYPFLAG_MEM_CACHEABLE:
+ flags |= IORESOURCE_CACHEABLE;
+ }
+
+ if (res->typflags & ACPI_RESOURCE_TYPFLAG_RW_MASK)
+ flags |= IORESOURCE_MEM_WRITEABLE;
+
+ break;
+ case ACPI_RESOURCE_TYPE_IO:
+ name = "IO";
+ flags = IORESOURCE_IO;
+ break;
+ case ACPI_RESOURCE_TYPE_BUSNO:
+ name = "BUS";
+ flags = IORESOURCE_BUS;
+ break;
+ default:
+ return ERR_PTR(-ENXIO);
+ }
+
+ *out = build_resource(name, res->addr_min, res->addr_len, flags);
+
+ pr_debug("%s: %llx-%llx (len=%llx, gr=%lld, xlate_off=%llx, resflags=%08lx)\n",
+ out->name,
+ res->addr_min, res->addr_max, res->addr_len,
+ res->addr_granularity, res->addr_xlate_off,
+ flags);
+
+ return next;
+}
+
+/* EFI already enumerated the bus for us, match our new pci devices with the efi
+ * handles
+ */
+static void efi_pci_fixup_dev_parent(struct pci_dev *dev)
+{
+ struct efi_pci_priv *priv = host_to_efi_pci(dev->bus->host);
+ struct pci_child *child;
+ struct pci_child_id id;
+
+ id.segmentno = priv->protocol->segmentno;
+ id.busno = dev->bus->number;
+ id.devno = PCI_SLOT(dev->devfn);
+ id.funcno = PCI_FUNC(dev->devfn);
+
+ list_for_each_entry(child, &priv->children, list) {
+ if (IS_ERR(child->protocol))
+ continue;
+
+ if (!child->protocol) {
+ struct efi_device *efichild = to_efi_device(child->dev);
+ efi_status_t efiret;
+
+ BS->handle_protocol(efichild->handle, &EFI_PCI_IO_PROTOCOL_GUID,
+ (void **)&child->protocol);
+ if (!child->protocol) {
+ child->protocol = ERR_PTR(-ENODEV);
+ continue;
+ }
+
+ efiret = child->protocol->get_location(child->protocol,
+ &child->id.segmentno,
+ &child->id.busno,
+ &child->id.devno,
+ &child->id.funcno);
+
+ if (EFI_ERROR(efiret)) {
+ child->protocol = ERR_PTR(-efi_errno(efiret));
+ continue;
+ }
+ }
+
+ if (pci_child_id_equal(&child->id, &id)) {
+ dev->dev.priv = child->protocol;
+ dev->dev.parent = child->dev;
+ return;
+ }
+ }
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, efi_pci_fixup_dev_parent);
+
+static int efi_pci_probe(struct efi_device *efidev)
+{
+ struct device_d *child;
+ struct efi_pci_priv *priv;
+ efi_status_t efiret;
+ void *resources;
+ struct resource resource;
+ u8 *res;
+
+ priv = xzalloc(sizeof(*priv));
+
+ BS->handle_protocol(efidev->handle, &EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID,
+ (void **)&priv->protocol);
+ if (!priv->protocol)
+ return -ENODEV;
+
+ efiret = priv->protocol->configuration(priv->protocol, &resources);
+ if (EFI_ERROR(efiret))
+ return -efi_errno(efiret);
+
+ res = resources;
+
+ while (1) {
+ res = acpi_parse_resource(res, &resource);
+
+ if (IS_ERR(res))
+ return PTR_ERR(res);
+
+ if (!res)
+ break;
+
+ if ((resource.flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH))
+ == (IORESOURCE_MEM | IORESOURCE_PREFETCH)) {
+ priv->pci.mem_pref_resource = &priv->mem_pref;
+ priv->mem_pref = resource;
+ } else if (resource.flags & IORESOURCE_MEM) {
+ priv->pci.mem_resource = &priv->mem;
+ priv->mem = resource;
+ } else if (resource.flags & IORESOURCE_IO) {
+ priv->pci.io_resource = &priv->io;
+ priv->io = resource;
+ }
+ }
+
+ priv->pci.parent = &efidev->dev;
+ priv->pci.pci_ops = &efi_pci_ops;
+
+ INIT_LIST_HEAD(&priv->children);
+
+ device_for_each_child(&efidev->dev, child) {
+ struct pci_child *pci_child;
+ struct efi_device *efichild = to_efi_device(child);
+
+ if (!efi_device_has_guid(efichild, EFI_PCI_IO_PROTOCOL_GUID))
+ continue;
+
+ pci_child = xzalloc(sizeof(*pci_child));
+
+ pci_child->dev = &efichild->dev;
+
+ /*
+ * regiser_pci_controller can reconfigure bridge bus numbers,
+ * thus we only collect the child node handles here, but
+ * don't yet call GetLocation on them
+ */
+ list_add_tail(&pci_child->list, &priv->children);
+ };
+
+ register_pci_controller(&priv->pci);
+
+ return 0;
+}
+
+static struct efi_driver efi_pci_driver = {
+ .driver = {
+ .name = "efi-pci",
+ },
+ .probe = efi_pci_probe,
+ .guid = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID,
+};
+device_efi_driver(efi_pci_driver);
diff --git a/drivers/pci/pci-efi.h b/drivers/pci/pci-efi.h
new file mode 100644
index 0000000000..1943461cdf
--- /dev/null
+++ b/drivers/pci/pci-efi.h
@@ -0,0 +1,343 @@
+// SPDX-License-Identifier: GPL-2.0
+#ifndef __PCI_EFI_H_
+#define __PCI_EFI_H_
+
+#include <efi.h>
+
+struct efi_pci_root_bridge_io_protocol;
+struct efi_pci_io_protocol;
+
+enum efi_pci_protocol_width {
+ EFI_PCI_WIDTH_U8,
+ EFI_PCI_WIDTH_U16,
+ EFI_PCI_WIDTH_U32,
+ EFI_PCI_WIDTH_U64,
+ EFI_PCI_WIDTH_FIFO_U8,
+ EFI_PCI_WIDTH_FIFO_U16,
+ EFI_PCI_WIDTH_FIFO_U32,
+ EFI_PCI_WIDTH_FIFO_U64,
+ EFI_PCI_WIDTH_FILL_U8,
+ EFI_PCI_WIDTH_FILL_U16,
+ EFI_PCI_WIDTH_FILL_U32,
+ EFI_PCI_WIDTH_FILL_U64,
+ EFI_PCI_WIDTH_MAX
+};
+
+#define EFI_PCI_IO_PASS_THROUGH_BAR 0xff
+
+typedef efi_status_t (EFIAPI *efi_pci_root_bridge_io_protocol_io_mem) (
+ struct efi_pci_root_bridge_io_protocol *this,
+ enum efi_pci_protocol_width width,
+ u64 addr,
+ size_t count,
+ void *buf
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_io_protocol_io_mem) (
+ struct efi_pci_io_protocol *this,
+ enum efi_pci_protocol_width width,
+ u8 bar,
+ u64 offset,
+ size_t count,
+ void *buf
+);
+
+struct efi_pci_root_bridge_io_protocol_access {
+ efi_pci_root_bridge_io_protocol_io_mem read;
+ efi_pci_root_bridge_io_protocol_io_mem write;
+};
+
+struct efi_pci_io_protocol_access {
+ efi_pci_io_protocol_io_mem read;
+ efi_pci_io_protocol_io_mem write;
+};
+
+#define EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001
+#define EFI_PCI_ATTRIBUTE_ISA_IO 0x0002
+#define EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO 0x0004
+#define EFI_PCI_ATTRIBUTE_VGA_MEMORY 0x0008
+#define EFI_PCI_ATTRIBUTE_VGA_IO 0x0010
+#define EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO 0x0020
+#define EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO 0x0040
+#define EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080
+#define EFI_PCI_ATTRIBUTE_IO 0x0100
+#define EFI_PCI_ATTRIBUTE_MEMORY 0x0200
+#define EFI_PCI_ATTRIBUTE_BUS_MASTER 0x0400
+#define EFI_PCI_ATTRIBUTE_MEMORY_CACHED 0x0800
+#define EFI_PCI_ATTRIBUTE_MEMORY_DISABLE 0x1000
+#define EFI_PCI_ATTRIBUTE_EMBEDDED_DEVICE 0x2000
+#define EFI_PCI_ATTRIBUTE_EMBEDDED_ROM 0x4000
+#define EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000
+#define EFI_PCI_ATTRIBUTE_ISA_IO_16 0x10000
+#define EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000
+#define EFI_PCI_ATTRIBUTE_VGA_IO_16 0x40000
+
+typedef efi_status_t (EFIAPI *efi_pci_root_bridge_io_protocol_poll_io_mem) (
+ struct efi_pci_root_bridge_io_protocol *this,
+ enum efi_pci_protocol_width width,
+ u64 address,
+ u64 mask,
+ u64 value,
+ u64 delay,
+ u64 *result
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_io_protocol_poll_io_mem) (
+ struct efi_pci_io_protocol *this,
+ enum efi_pci_protocol_width width,
+ u8 bar,
+ u64 offset,
+ u64 mask,
+ u64 value,
+ u64 delay,
+ u64 *result
+);
+
+enum efi_pci_root_bridge_io_protocol_operation {
+ EFI_PCI_ROOT_BRIGE_IO_OP_BUS_MASTER_READ,
+ EFI_PCI_ROOT_BRIGE_IO_OP_BUS_MASTER_WRITE,
+ EFI_PCI_ROOT_BRIGE_IO_OP_BUS_MASTER_COMMON_BUFFER,
+ EFI_PCI_ROOT_BRIGE_IO_OP_BUS_MASTER_READ64,
+ EFI_PCI_ROOT_BRIGE_IO_OP_BUS_MASTER_WRITE64,
+ EFI_PCI_ROOT_BRIGE_IO_OP_BUS_MASTER_COMMON_BUFFER64,
+ EFI_PCI_ROOT_BRIGE_IO_OP_MAX
+};
+
+enum efi_pci_io_protocol_operation {
+ EFI_PCI_IO_OP_BUS_MASTER_READ,
+ EFI_PCI_IO_OP_BUS_MASTER_WRITE,
+ EFI_PCI_IO_OP_BUS_MASTER_COMMON_BUFFER,
+ EFI_PCI_IO_OP_MAX
+};
+
+typedef efi_status_t (EFIAPI *efi_pci_root_bridge_io_protocol_copy_mem) (
+ struct efi_pci_root_bridge_io_protocol *this,
+ enum efi_pci_protocol_width width,
+ u64 dst,
+ u64 src,
+ size_t count
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_io_protocol_copy_mem) (
+ struct efi_pci_io_protocol *this,
+ enum efi_pci_protocol_width width,
+ u8 dst_bar,
+ u64 dst_offset,
+ u8 src_bar,
+ u64 src_offset,
+ size_t count
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_root_bridge_io_protocol_map) (
+ struct efi_pci_root_bridge_io_protocol *this,
+ enum efi_pci_root_bridge_io_protocol_operation operation,
+ void *hostaddr,
+ size_t *nbytes,
+ efi_physical_addr_t *devaddr,
+ void **mapping
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_io_protocol_map) (
+ struct efi_pci_io_protocol *this,
+ enum efi_pci_io_protocol_operation operation,
+ void *hostaddr,
+ size_t *nbytes,
+ efi_physical_addr_t *devaddr,
+ void **mapping
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_root_bridge_io_protocol_unmap) (
+ struct efi_pci_root_bridge_io_protocol *this,
+ void *mapping
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_io_protocol_unmap) (
+ struct efi_pci_io_protocol *this,
+ void *mapping
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_root_bridge_io_protocol_allocate_buffer) (
+ struct efi_pci_root_bridge_io_protocol *this,
+ enum efi_allocate_type alloctype,
+ enum efi_memory_type memtype,
+ size_t npages,
+ void **hostaddr,
+ u64 attrs
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_io_protocol_allocate_buffer) (
+ struct efi_pci_io_protocol *this,
+ enum efi_allocate_type alloctype,
+ enum efi_memory_type memtype,
+ size_t npages,
+ void **hostaddr,
+ u64 attrs
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_root_bridge_io_protocol_free_buffer) (
+ struct efi_pci_root_bridge_io_protocol *this,
+ size_t npages,
+ void *hostaddr
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_io_protocol_free_buffer) (
+ struct efi_pci_io_protocol *this,
+ size_t npages,
+ void *hostaddr
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_root_bridge_io_protocol_flush) (
+ struct efi_pci_root_bridge_io_protocol *this
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_io_protocol_flush) (
+ struct efi_pci_io_protocol *this
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_io_protocol_get_location) (
+ struct efi_pci_io_protocol *this,
+ size_t *segmentno,
+ size_t *busno,
+ size_t *deveno,
+ size_t *funcno
+);
+
+enum efi_io_protocol_attribute_operation {
+ PCI_IO_ATTR_OP_GET,
+ PCI_IO_ATTR_OP_SET,
+ PCI_IO_ATTR_OP_ENABLE,
+ PCI_IO_ATTR_OP_DISABLE,
+ PCI_IO_ATTR_OP_SUPPORTED,
+ PCI_IO_ATTR_OP_MAX,
+};
+
+typedef efi_status_t (EFIAPI *efi_pci_io_protocol_attributes) (
+ struct efi_pci_io_protocol *this,
+ enum efi_io_protocol_attribute_operation operation,
+ u64 attrs,
+ u64 *result
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_root_bridge_io_protocol_get_attributes) (
+ struct efi_pci_root_bridge_io_protocol *this,
+ u64 *supports,
+ u64 *attrs
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_io_protocol_get_bar_attributes) (
+ struct efi_pci_io_protocol *this,
+ u8 bar,
+ u64 *supports,
+ void **resources
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_root_bridge_io_protocol_set_attributes) (
+ struct efi_pci_root_bridge_io_protocol *this,
+ u64 attrs,
+ u64 *resource_base,
+ u64 *resource_len
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_io_protocol_set_bar_attributes) (
+ struct efi_pci_io_protocol *this,
+ u64 attrs,
+ u8 bar,
+ u64 *offset,
+ u64 *len
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_root_bridge_io_protocol_configuration) (
+ struct efi_pci_root_bridge_io_protocol *this,
+ void **resources
+);
+
+typedef efi_status_t (EFIAPI *efi_pci_io_protocol_config) (
+ struct efi_pci_io_protocol *this,
+ enum efi_pci_protocol_width width,
+ u32 offset,
+ size_t count,
+ void *buffer
+);
+
+struct efi_pci_io_protocol_config_access {
+ efi_pci_io_protocol_config read;
+ efi_pci_io_protocol_config write;
+};
+
+struct __packed efi_acpi_resource {
+#define ACPI_RESOURCE_DESC_TAG 0x8A
+#define ACPI_RESOURCE_END_TAG 0x79
+ u8 asd; /* 0x8A */
+ u16 len; /* 0x2B */
+#define ACPI_RESOURCE_TYPE_MEM 0
+#define ACPI_RESOURCE_TYPE_IO 1
+#define ACPI_RESOURCE_TYPE_BUSNO 2
+ u8 restype;
+ u8 genflags;
+#define ACPI_RESOURCE_TYPFLAG_TTP_MASK 0b00100000
+#define ACPI_RESOURCE_TYPFLAG_MTP_MASK 0b00011000
+#define ACPI_RESOURCE_TYPFLAG_MTP_MEM 0
+#define ACPI_RESOURCE_TYPFLAG_MTP_RESERVED 1
+#define ACPI_RESOURCE_TYPFLAG_MTP_ACPI 2
+#define ACPI_RESOURCE_TYPFLAG_MTP_NVS 3
+#define ACPI_RESOURCE_TYPFLAG_MEM_MASK 0b00000110
+#define ACPI_RESOURCE_TYPFLAG_MEM_NONCACHEABLE 0
+#define ACPI_RESOURCE_TYPFLAG_MEM_CACHEABLE 1
+#define ACPI_RESOURCE_TYPFLAG_MEM_WC 2
+#define ACPI_RESOURCE_TYPFLAG_MEM_PREF 3
+#define ACPI_RESOURCE_TYPFLAG_RW_MASK 0b00000001
+ u8 typflags;
+ u64 addr_granularity;
+ u64 addr_min;
+ u64 addr_max;
+ u64 addr_xlate_off;
+ u64 addr_len;
+};
+
+struct efi_pci_root_bridge_io_protocol {
+ efi_handle_t parent_handle;
+ efi_pci_root_bridge_io_protocol_poll_io_mem poll_mem;
+ efi_pci_root_bridge_io_protocol_poll_io_mem poll_io;
+ struct efi_pci_root_bridge_io_protocol_access mem;
+ struct efi_pci_root_bridge_io_protocol_access io;
+ struct efi_pci_root_bridge_io_protocol_access pci;
+ efi_pci_root_bridge_io_protocol_copy_mem copy_mem;
+ efi_pci_root_bridge_io_protocol_map map;
+ efi_pci_root_bridge_io_protocol_unmap unmap;
+ efi_pci_root_bridge_io_protocol_allocate_buffer allocate_buffer;
+ efi_pci_root_bridge_io_protocol_free_buffer free_buffer;
+ efi_pci_root_bridge_io_protocol_flush flush;
+ efi_pci_root_bridge_io_protocol_get_attributes get_attributes;
+ efi_pci_root_bridge_io_protocol_set_attributes set_attributes;
+ efi_pci_root_bridge_io_protocol_configuration configuration;
+ u32 segmentno;
+};
+
+struct efi_pci_io_protocol {
+ efi_pci_io_protocol_poll_io_mem poll_mem;
+ efi_pci_io_protocol_poll_io_mem poll_io;
+ struct efi_pci_io_protocol_access mem;
+ struct efi_pci_io_protocol_access io;
+ struct efi_pci_io_protocol_access pci;
+ efi_pci_io_protocol_copy_mem copy_mem;
+ efi_pci_io_protocol_map map;
+ efi_pci_io_protocol_unmap unmap;
+ efi_pci_io_protocol_allocate_buffer allocate_buffer;
+ efi_pci_io_protocol_free_buffer free_buffer;
+ efi_pci_io_protocol_flush flush;
+ efi_pci_io_protocol_get_location get_location;
+ efi_pci_io_protocol_attributes attributes;
+ efi_pci_io_protocol_get_bar_attributes get_bar_attributes;
+ efi_pci_io_protocol_set_bar_attributes set_bar_attributes;
+ u64 rom_size;
+ void *rom_image;
+};
+
+#define EFI_PCI_ADDRESS(bus, dev, func, reg) \
+ (u64) ( \
+ (((size_t) bus) << 24) | \
+ (((size_t) dev) << 16) | \
+ (((size_t) func) << 8) | \
+ (((size_t) (reg)) < 256 ? ((size_t) (reg)) : ((u64)(reg)) << 32))
+
+#endif