2012-08-23 16:37:25

by Matthew Garrett

[permalink] [raw]
Subject: Use PCI ROMs from EFI boot services

V3 just fixes all the casting issues and incorporates David's change in
search ordering.


2012-08-23 16:37:57

by Matthew Garrett

[permalink] [raw]
Subject: [PATCH V3 3/4] PCI: Add support for non-BAR ROMs

Platforms may provide their own mechanisms for obtaining ROMs. Add support
for using data provided by the platform in that case.

Signed-off-by: Matthew Garrett <[email protected]>
---
drivers/pci/rom.c | 11 +++++++++--
include/linux/pci.h | 2 ++
2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index 48ebdb2..46026e4 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -118,11 +118,17 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
void __iomem *rom;

/*
+ * Some devices may provide ROMs via a source other than the BAR
+ */
+ if (pdev->rom && pdev->romlen) {
+ *size = pdev->romlen;
+ return phys_to_virt((phys_addr_t)pdev->rom);
+ /*
* IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy
* memory map if the VGA enable bit of the Bridge Control register is
* set for embedded VGA.
*/
- if (res->flags & IORESOURCE_ROM_SHADOW) {
+ } else if (res->flags & IORESOURCE_ROM_SHADOW) {
/* primary video rom always starts here */
start = (loff_t)0xC0000;
*size = 0x20000; /* cover C000:0 through E000:0 */
@@ -219,7 +225,8 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
return;

- iounmap(rom);
+ if (!pdev->rom || !pdev->romlen)
+ iounmap(rom);

/* Disable again before continuing, leave enabled if pci=rom */
if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW)))
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 6a2625c..2668bb9 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -355,6 +355,8 @@ struct pci_dev {
};
struct pci_ats *ats; /* Address Translation Service */
#endif
+ void *rom; /* Physical pointer to ROM if it's not from the BAR */
+ size_t romlen; /* Length of ROM if it's not from the BAR */
};

static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
--
1.7.11.2

2012-08-23 16:38:07

by Matthew Garrett

[permalink] [raw]
Subject: [PATCH V3 1/4] EFI: Stash ROMs if they're not in the PCI BAR

EFI provides support for providing PCI ROMs via means other than the ROM
BAR. This support vanishes after we've exited boot services, so add support
for stashing copies of the ROMs in setup_data if they're not otherwise
available.
---
arch/x86/boot/compressed/eboot.c | 118 +++++++++++++++++++++++++++++++++++++++
arch/x86/include/asm/bootparam.h | 1 +
arch/x86/include/asm/pci.h | 12 ++++
include/linux/efi.h | 71 +++++++++++++++++++++++
4 files changed, 202 insertions(+)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index b3e0227..8630578 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -8,6 +8,7 @@
* ----------------------------------------------------------------------- */

#include <linux/efi.h>
+#include <linux/pci.h>
#include <asm/efi.h>
#include <asm/setup.h>
#include <asm/desc.h>
@@ -243,6 +244,121 @@ static void find_bits(unsigned long mask, u8 *pos, u8 *size)
*size = len;
}

+static efi_status_t setup_efi_pci(struct boot_params *params)
+{
+ efi_pci_io_protocol *pci;
+ efi_status_t status;
+ void **pci_handle;
+ efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
+ unsigned long nr_pci, size = 0;
+ int i;
+ struct setup_data *data;
+
+ data = (struct setup_data *)params->hdr.setup_data;
+
+ while (data && data->next)
+ data = (struct setup_data *)data->next;
+
+ status = efi_call_phys5(sys_table->boottime->locate_handle,
+ EFI_LOCATE_BY_PROTOCOL, &pci_proto,
+ NULL, &size, pci_handle);
+
+ if (status == EFI_BUFFER_TOO_SMALL) {
+ status = efi_call_phys3(sys_table->boottime->allocate_pool,
+ EFI_LOADER_DATA, size, &pci_handle);
+
+ if (status != EFI_SUCCESS)
+ return status;
+
+ status = efi_call_phys5(sys_table->boottime->locate_handle,
+ EFI_LOCATE_BY_PROTOCOL, &pci_proto,
+ NULL, &size, pci_handle);
+ }
+
+ if (status != EFI_SUCCESS)
+ goto free_handle;
+
+ nr_pci = size / sizeof(void *);
+ for (i = 0; i < nr_pci; i++) {
+ void *h = pci_handle[i];
+ uint64_t attributes;
+ struct pci_setup_rom *rom;
+
+ status = efi_call_phys3(sys_table->boottime->handle_protocol,
+ h, &pci_proto, &pci);
+
+ if (status != EFI_SUCCESS)
+ continue;
+
+ if (!pci)
+ continue;
+
+ status = efi_call_phys4(pci->attributes, pci,
+ EfiPciIoAttributeOperationGet, 0,
+ &attributes);
+
+ if (status != EFI_SUCCESS)
+ continue;
+
+ if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)
+ continue;
+
+ if (!pci->romimage || !pci->romsize)
+ continue;
+
+ size = pci->romsize + sizeof(*rom);
+
+ status = efi_call_phys3(sys_table->boottime->allocate_pool,
+ EFI_LOADER_DATA, size, &rom);
+
+ if (status != EFI_SUCCESS)
+ continue;
+
+ rom->data.type = SETUP_PCI;
+ rom->data.len = size - sizeof(struct setup_data);
+ rom->data.next = 0;
+ rom->pcilen = pci->romsize;
+
+ status = efi_call_phys5(pci->pci.read, pci,
+ EfiPciIoWidthUint16, PCI_VENDOR_ID,
+ 1, &(rom->vendor));
+
+ if (status != EFI_SUCCESS)
+ goto free_struct;
+
+ status = efi_call_phys5(pci->pci.read, pci,
+ EfiPciIoWidthUint16, PCI_DEVICE_ID,
+ 1, &(rom->devid));
+
+ if (status != EFI_SUCCESS)
+ goto free_struct;
+
+ status = efi_call_phys5(pci->get_location, pci,
+ &(rom->segment), &(rom->bus),
+ &(rom->device), &(rom->function));
+
+ if (status != EFI_SUCCESS)
+ goto free_struct;
+
+ memcpy(rom->romdata, pci->romimage, pci->romsize);
+
+ if (data)
+ data->next = (uint64_t)rom;
+ else
+ params->hdr.setup_data = (uint64_t)rom;
+
+ data = (struct setup_data *)rom;
+
+ continue;
+ free_struct:
+ efi_call_phys1(sys_table->boottime->free_pool, rom);
+ }
+
+free_handle:
+ efi_call_phys1(sys_table->boottime->free_pool, pci_handle);
+ return status;
+}
+
/*
* See if we have Graphics Output Protocol
*/
@@ -1020,6 +1136,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,

setup_graphics(boot_params);

+ setup_efi_pci(boot_params);
+
status = efi_call_phys3(sys_table->boottime->allocate_pool,
EFI_LOADER_DATA, sizeof(*gdt),
(void **)&gdt);
diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h
index 2ad874c..92862cd 100644
--- a/arch/x86/include/asm/bootparam.h
+++ b/arch/x86/include/asm/bootparam.h
@@ -13,6 +13,7 @@
#define SETUP_NONE 0
#define SETUP_E820_EXT 1
#define SETUP_DTB 2
+#define SETUP_PCI 3

/* extensible setup data list node */
struct setup_data {
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index df75d07..11491d1 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -171,4 +171,16 @@ cpumask_of_pcibus(const struct pci_bus *bus)
}
#endif

+struct pci_setup_rom {
+ struct setup_data data;
+ uint16_t vendor;
+ uint16_t devid;
+ uint64_t pcilen;
+ unsigned long segment;
+ unsigned long bus;
+ unsigned long device;
+ unsigned long function;
+ uint8_t romdata[0];
+};
+
#endif /* _ASM_X86_PCI_H */
diff --git a/include/linux/efi.h b/include/linux/efi.h
index ec45ccd..bf7e867 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -196,6 +196,77 @@ typedef struct {
void *create_event_ex;
} efi_boot_services_t;

+typedef enum {
+ EfiPciIoWidthUint8,
+ EfiPciIoWidthUint16,
+ EfiPciIoWidthUint32,
+ EfiPciIoWidthUint64,
+ EfiPciIoWidthFifoUint8,
+ EfiPciIoWidthFifoUint16,
+ EfiPciIoWidthFifoUint32,
+ EfiPciIoWidthFifoUint64,
+ EfiPciIoWidthFillUint8,
+ EfiPciIoWidthFillUint16,
+ EfiPciIoWidthFillUint32,
+ EfiPciIoWidthFillUint64,
+ EfiPciIoWidthMaximum
+} EFI_PCI_IO_PROTOCOL_WIDTH;
+
+typedef enum {
+ EfiPciIoAttributeOperationGet,
+ EfiPciIoAttributeOperationSet,
+ EfiPciIoAttributeOperationEnable,
+ EfiPciIoAttributeOperationDisable,
+ EfiPciIoAttributeOperationSupported,
+ EfiPciIoAttributeOperationMaximum
+} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION;
+
+
+typedef struct {
+ void *read;
+ void *write;
+} efi_pci_io_protocol_access_t;
+
+typedef struct {
+ void *poll_mem;
+ void *poll_io;
+ efi_pci_io_protocol_access_t mem;
+ efi_pci_io_protocol_access_t io;
+ efi_pci_io_protocol_access_t pci;
+ void *copy_mem;
+ void *map;
+ void *unmap;
+ void *allocate_buffer;
+ void *free_buffer;
+ void *flush;
+ void *get_location;
+ void *attributes;
+ void *get_bar_attributes;
+ void *set_bar_attributes;
+ uint64_t romsize;
+ void *romimage;
+} efi_pci_io_protocol;
+
+#define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001
+#define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002
+#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO 0x0004
+#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY 0x0008
+#define EFI_PCI_IO_ATTRIBUTE_VGA_IO 0x0010
+#define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO 0x0020
+#define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO 0x0040
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080
+#define EFI_PCI_IO_ATTRIBUTE_IO 0x0100
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY 0x0200
+#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER 0x0400
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED 0x0800
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000
+#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE 0x2000
+#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM 0x4000
+#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000
+#define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 0x10000
+#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000
+#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000
+
/*
* Types and defines for EFI ResetSystem
*/
--
1.7.11.2

2012-08-23 16:38:01

by Matthew Garrett

[permalink] [raw]
Subject: [PATCH V3 2/4] PCI: Add pcibios_add_device

Platforms may want to provide architecture-specific functionality during
PCI enumeration. Add a pcibios_add_device() call that architectures can
override to do so.

Signed-off-by: Matthew Garrett <[email protected]>
---
drivers/pci/bus.c | 5 +++++
drivers/pci/pci.c | 13 +++++++++++++
include/linux/pci.h | 1 +
3 files changed, 19 insertions(+)

diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 4b0970b..e2f447e 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -166,6 +166,11 @@ int pci_bus_add_device(struct pci_dev *dev)
int retval;

pci_fixup_device(pci_fixup_final, dev);
+
+ retval = pcibios_add_device(dev);
+ if (retval)
+ return retval;
+
retval = device_add(&dev->dev);
if (retval)
return retval;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index f3ea977..5a9a4d8 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1385,6 +1385,19 @@ void pcim_pin_device(struct pci_dev *pdev)
dr->pinned = 1;
}

+/*
+ * pcibios_add_device - provide arch specific hooks when adding device dev
+ * @dev: the PCI device being added
+ *
+ * Permits the platform to provide architecture specific functionality when
+ * devices are added. This is the default implementation. Architecture
+ * implementations can override this.
+ */
+int __attribute__ ((weak)) pcibios_add_device (struct pci_dev *dev)
+{
+ return 0;
+}
+
/**
* pcibios_disable_device - disable arch specific PCI resources for device dev
* @dev: the PCI device to disable
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 5faa831..6a2625c 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1582,6 +1582,7 @@ void pcibios_disable_device(struct pci_dev *dev);
void pcibios_set_master(struct pci_dev *dev);
int pcibios_set_pcie_reset_state(struct pci_dev *dev,
enum pcie_reset_state state);
+int pcibios_add_device(struct pci_dev *dev);

#ifdef CONFIG_PCI_MMCONFIG
extern void __init pci_mmcfg_early_init(void);
--
1.7.11.2

2012-08-23 16:37:53

by Matthew Garrett

[permalink] [raw]
Subject: [PATCH V3 4/4] X86: Use PCI setup data

EFI can provide PCI ROMs out of band via boot services, which may not be
available after boot. Add support for using the data handed off to us by
the boot stub or bootloader.

Signed-off-by: Matthew Garrett <[email protected]>
---
arch/x86/pci/common.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)

diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 720e973f..3d2752f 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -17,6 +17,7 @@
#include <asm/io.h>
#include <asm/smp.h>
#include <asm/pci_x86.h>
+#include <asm/setup.h>

unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
PCI_PROBE_MMCONF;
@@ -608,6 +609,38 @@ unsigned int pcibios_assign_all_busses(void)
return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
}

+int pcibios_add_device(struct pci_dev *dev)
+{
+ struct setup_data *data;
+ struct pci_setup_rom *rom;
+ u64 pa_data;
+
+ if (boot_params.hdr.version < 0x0209)
+ return 0;
+
+ pa_data = boot_params.hdr.setup_data;
+ while (pa_data) {
+ data = phys_to_virt(pa_data);
+
+ if (data->type == SETUP_PCI) {
+ rom = (struct pci_setup_rom *)data;
+
+ if ((pci_domain_nr(dev->bus) == rom->segment) &&
+ (dev->bus->number == rom->bus) &&
+ (PCI_SLOT(dev->devfn) == rom->device) &&
+ (PCI_FUNC(dev->devfn) == rom->function) &&
+ (dev->vendor == rom->vendor) &&
+ (dev->device == rom->devid)) {
+ dev->rom = (void *)(pa_data +
+ offsetof(struct pci_setup_rom, romdata));
+ dev->romlen = rom->pcilen;
+ }
+ }
+ pa_data = data->next;
+ }
+ return 0;
+}
+
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
int err;
--
1.7.11.2

2012-08-23 23:44:49

by Bjorn Helgaas

[permalink] [raw]
Subject: Re: [PATCH V3 1/4] EFI: Stash ROMs if they're not in the PCI BAR

On Thu, Aug 23, 2012 at 10:36 AM, Matthew Garrett <[email protected]> wrote:
> EFI provides support for providing PCI ROMs via means other than the ROM
> BAR. This support vanishes after we've exited boot services, so add support
> for stashing copies of the ROMs in setup_data if they're not otherwise
> available.

-ENO_SIGNED_OFF_BY

I'll add it if you confirm it.

> ---
> arch/x86/boot/compressed/eboot.c | 118 +++++++++++++++++++++++++++++++++++++++
> arch/x86/include/asm/bootparam.h | 1 +
> arch/x86/include/asm/pci.h | 12 ++++
> include/linux/efi.h | 71 +++++++++++++++++++++++
> 4 files changed, 202 insertions(+)
>
> diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
> index b3e0227..8630578 100644
> --- a/arch/x86/boot/compressed/eboot.c
> +++ b/arch/x86/boot/compressed/eboot.c
> @@ -8,6 +8,7 @@
> * ----------------------------------------------------------------------- */
>
> #include <linux/efi.h>
> +#include <linux/pci.h>
> #include <asm/efi.h>
> #include <asm/setup.h>
> #include <asm/desc.h>
> @@ -243,6 +244,121 @@ static void find_bits(unsigned long mask, u8 *pos, u8 *size)
> *size = len;
> }
>
> +static efi_status_t setup_efi_pci(struct boot_params *params)
> +{
> + efi_pci_io_protocol *pci;
> + efi_status_t status;
> + void **pci_handle;
> + efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
> + unsigned long nr_pci, size = 0;
> + int i;
> + struct setup_data *data;
> +
> + data = (struct setup_data *)params->hdr.setup_data;
> +
> + while (data && data->next)
> + data = (struct setup_data *)data->next;
> +
> + status = efi_call_phys5(sys_table->boottime->locate_handle,
> + EFI_LOCATE_BY_PROTOCOL, &pci_proto,
> + NULL, &size, pci_handle);
> +
> + if (status == EFI_BUFFER_TOO_SMALL) {
> + status = efi_call_phys3(sys_table->boottime->allocate_pool,
> + EFI_LOADER_DATA, size, &pci_handle);
> +
> + if (status != EFI_SUCCESS)
> + return status;
> +
> + status = efi_call_phys5(sys_table->boottime->locate_handle,
> + EFI_LOCATE_BY_PROTOCOL, &pci_proto,
> + NULL, &size, pci_handle);
> + }
> +
> + if (status != EFI_SUCCESS)
> + goto free_handle;
> +
> + nr_pci = size / sizeof(void *);
> + for (i = 0; i < nr_pci; i++) {
> + void *h = pci_handle[i];
> + uint64_t attributes;
> + struct pci_setup_rom *rom;
> +
> + status = efi_call_phys3(sys_table->boottime->handle_protocol,
> + h, &pci_proto, &pci);
> +
> + if (status != EFI_SUCCESS)
> + continue;
> +
> + if (!pci)
> + continue;
> +
> + status = efi_call_phys4(pci->attributes, pci,
> + EfiPciIoAttributeOperationGet, 0,
> + &attributes);
> +
> + if (status != EFI_SUCCESS)
> + continue;
> +
> + if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)
> + continue;
> +
> + if (!pci->romimage || !pci->romsize)
> + continue;
> +
> + size = pci->romsize + sizeof(*rom);
> +
> + status = efi_call_phys3(sys_table->boottime->allocate_pool,
> + EFI_LOADER_DATA, size, &rom);
> +
> + if (status != EFI_SUCCESS)
> + continue;
> +
> + rom->data.type = SETUP_PCI;
> + rom->data.len = size - sizeof(struct setup_data);
> + rom->data.next = 0;
> + rom->pcilen = pci->romsize;
> +
> + status = efi_call_phys5(pci->pci.read, pci,
> + EfiPciIoWidthUint16, PCI_VENDOR_ID,
> + 1, &(rom->vendor));
> +
> + if (status != EFI_SUCCESS)
> + goto free_struct;
> +
> + status = efi_call_phys5(pci->pci.read, pci,
> + EfiPciIoWidthUint16, PCI_DEVICE_ID,
> + 1, &(rom->devid));
> +
> + if (status != EFI_SUCCESS)
> + goto free_struct;
> +
> + status = efi_call_phys5(pci->get_location, pci,
> + &(rom->segment), &(rom->bus),
> + &(rom->device), &(rom->function));
> +
> + if (status != EFI_SUCCESS)
> + goto free_struct;
> +
> + memcpy(rom->romdata, pci->romimage, pci->romsize);
> +
> + if (data)
> + data->next = (uint64_t)rom;
> + else
> + params->hdr.setup_data = (uint64_t)rom;
> +
> + data = (struct setup_data *)rom;
> +
> + continue;
> + free_struct:
> + efi_call_phys1(sys_table->boottime->free_pool, rom);
> + }
> +
> +free_handle:
> + efi_call_phys1(sys_table->boottime->free_pool, pci_handle);
> + return status;
> +}
> +
> /*
> * See if we have Graphics Output Protocol
> */
> @@ -1020,6 +1136,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
>
> setup_graphics(boot_params);
>
> + setup_efi_pci(boot_params);
> +
> status = efi_call_phys3(sys_table->boottime->allocate_pool,
> EFI_LOADER_DATA, sizeof(*gdt),
> (void **)&gdt);
> diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h
> index 2ad874c..92862cd 100644
> --- a/arch/x86/include/asm/bootparam.h
> +++ b/arch/x86/include/asm/bootparam.h
> @@ -13,6 +13,7 @@
> #define SETUP_NONE 0
> #define SETUP_E820_EXT 1
> #define SETUP_DTB 2
> +#define SETUP_PCI 3
>
> /* extensible setup data list node */
> struct setup_data {
> diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
> index df75d07..11491d1 100644
> --- a/arch/x86/include/asm/pci.h
> +++ b/arch/x86/include/asm/pci.h
> @@ -171,4 +171,16 @@ cpumask_of_pcibus(const struct pci_bus *bus)
> }
> #endif
>
> +struct pci_setup_rom {
> + struct setup_data data;
> + uint16_t vendor;
> + uint16_t devid;
> + uint64_t pcilen;
> + unsigned long segment;
> + unsigned long bus;
> + unsigned long device;
> + unsigned long function;
> + uint8_t romdata[0];
> +};
> +
> #endif /* _ASM_X86_PCI_H */
> diff --git a/include/linux/efi.h b/include/linux/efi.h
> index ec45ccd..bf7e867 100644
> --- a/include/linux/efi.h
> +++ b/include/linux/efi.h
> @@ -196,6 +196,77 @@ typedef struct {
> void *create_event_ex;
> } efi_boot_services_t;
>
> +typedef enum {
> + EfiPciIoWidthUint8,
> + EfiPciIoWidthUint16,
> + EfiPciIoWidthUint32,
> + EfiPciIoWidthUint64,
> + EfiPciIoWidthFifoUint8,
> + EfiPciIoWidthFifoUint16,
> + EfiPciIoWidthFifoUint32,
> + EfiPciIoWidthFifoUint64,
> + EfiPciIoWidthFillUint8,
> + EfiPciIoWidthFillUint16,
> + EfiPciIoWidthFillUint32,
> + EfiPciIoWidthFillUint64,
> + EfiPciIoWidthMaximum
> +} EFI_PCI_IO_PROTOCOL_WIDTH;
> +
> +typedef enum {
> + EfiPciIoAttributeOperationGet,
> + EfiPciIoAttributeOperationSet,
> + EfiPciIoAttributeOperationEnable,
> + EfiPciIoAttributeOperationDisable,
> + EfiPciIoAttributeOperationSupported,
> + EfiPciIoAttributeOperationMaximum
> +} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION;
> +
> +
> +typedef struct {
> + void *read;
> + void *write;
> +} efi_pci_io_protocol_access_t;
> +
> +typedef struct {
> + void *poll_mem;
> + void *poll_io;
> + efi_pci_io_protocol_access_t mem;
> + efi_pci_io_protocol_access_t io;
> + efi_pci_io_protocol_access_t pci;
> + void *copy_mem;
> + void *map;
> + void *unmap;
> + void *allocate_buffer;
> + void *free_buffer;
> + void *flush;
> + void *get_location;
> + void *attributes;
> + void *get_bar_attributes;
> + void *set_bar_attributes;
> + uint64_t romsize;
> + void *romimage;
> +} efi_pci_io_protocol;
> +
> +#define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001
> +#define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002
> +#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO 0x0004
> +#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY 0x0008
> +#define EFI_PCI_IO_ATTRIBUTE_VGA_IO 0x0010
> +#define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO 0x0020
> +#define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO 0x0040
> +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080
> +#define EFI_PCI_IO_ATTRIBUTE_IO 0x0100
> +#define EFI_PCI_IO_ATTRIBUTE_MEMORY 0x0200
> +#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER 0x0400
> +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED 0x0800
> +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000
> +#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE 0x2000
> +#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM 0x4000
> +#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000
> +#define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 0x10000
> +#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000
> +#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000
> +
> /*
> * Types and defines for EFI ResetSystem
> */
> --
> 1.7.11.2
>

2012-08-24 04:09:21

by Matthew Garrett

[permalink] [raw]
Subject: Re: [PATCH V3 1/4] EFI: Stash ROMs if they're not in the PCI BAR

On Thu, Aug 23, 2012 at 05:44:22PM -0600, Bjorn Helgaas wrote:
> On Thu, Aug 23, 2012 at 10:36 AM, Matthew Garrett <[email protected]> wrote:
> > EFI provides support for providing PCI ROMs via means other than the ROM
> > BAR. This support vanishes after we've exited boot services, so add support
> > for stashing copies of the ROMs in setup_data if they're not otherwise
> > available.
>
> -ENO_SIGNED_OFF_BY
>
> I'll add it if you confirm it.

Signed-off-by: Matthew Garrett <[email protected]>

--
Matthew Garrett | [email protected]

2012-08-24 09:30:24

by David Woodhouse

[permalink] [raw]
Subject: Re: Use PCI ROMs from EFI boot services

On Thu, 2012-08-23 at 12:36 -0400, Matthew Garrett wrote:
> V3 just fixes all the casting issues and incorporates David's change in
> search ordering.

I appreciate there are other issues with kexec under EFI, but let's not
make it worse. What is the plan for making this work *after* kexec? Do
these blobs get passed from the old kernel to the new? Does that work
already?

--
dwmw2


Attachments:
smime.p7s (6.03 kB)

2012-08-24 12:53:08

by Matthew Garrett

[permalink] [raw]
Subject: Re: Use PCI ROMs from EFI boot services

On Fri, Aug 24, 2012 at 10:30:01AM +0100, David Woodhouse wrote:
> On Thu, 2012-08-23 at 12:36 -0400, Matthew Garrett wrote:
> > V3 just fixes all the casting issues and incorporates David's change in
> > search ordering.
>
> I appreciate there are other issues with kexec under EFI, but let's not
> make it worse. What is the plan for making this work *after* kexec? Do
> these blobs get passed from the old kernel to the new? Does that work
> already?

kexec would presumably need to reconstruct the setup_data from the PCI
objects.

--
Matthew Garrett | [email protected]

2012-10-25 17:36:22

by Bjorn Helgaas

[permalink] [raw]
Subject: Re: Use PCI ROMs from EFI boot services

On Thu, Aug 23, 2012 at 10:36 AM, Matthew Garrett <[email protected]> wrote:
> V3 just fixes all the casting issues and incorporates David's change in
> search ordering.

I think there's still a section mismatch issue with these patches, so
I haven't merged them yet.

I rebased my pci/mjg-pci-roms-from-efi branch to v3.7-rc2, and if we
get this issue fixed I'll put it in -next as v3.8 material.

Bjorn