* ----------------------------------------------------------------------- */
 
 #include <linux/efi.h>
+#include <linux/pci.h>
 #include <asm/efi.h>
 #include <asm/setup.h>
 #include <asm/desc.h>
        *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
  */
 
        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);
 
        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
  */