Matthew Garrett e681abd
diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.c
Matthew Garrett e681abd
--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.c	2012-08-22 15:26:32.485522068 -0400
Matthew Garrett e681abd
+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.c	2012-08-22 15:25:40.529244868 -0400
Matthew Garrett e681abd
@@ -8,6 +8,7 @@
Matthew Garrett e681abd
  * ----------------------------------------------------------------------- */
Matthew Garrett e681abd
 
Matthew Garrett e681abd
 #include <linux/efi.h>
Matthew Garrett e681abd
+#include <linux/pci.h>
Matthew Garrett e681abd
 #include <asm/efi.h>
Matthew Garrett e681abd
 #include <asm/setup.h>
Matthew Garrett e681abd
 #include <asm/desc.h>
Matthew Garrett e681abd
@@ -243,6 +244,121 @@
Matthew Garrett e681abd
 	*size = len;
Matthew Garrett e681abd
 }
Matthew Garrett e681abd
 
Matthew Garrett e681abd
+static efi_status_t setup_efi_pci(struct boot_params *params)
Matthew Garrett e681abd
+{
Matthew Garrett e681abd
+	efi_pci_io_protocol *pci;
Matthew Garrett e681abd
+	efi_status_t status;
Matthew Garrett e681abd
+	void **pci_handle;
Matthew Garrett e681abd
+	efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
Matthew Garrett e681abd
+	unsigned long nr_pci, size = 0;
Matthew Garrett e681abd
+	int i;
Matthew Garrett e681abd
+	struct setup_data *data;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+	data = (struct setup_data *)params->hdr.setup_data;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+	while (data && data->next)
Matthew Garrett e681abd
+		data = (struct setup_data *)data->next;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+	status = efi_call_phys5(sys_table->boottime->locate_handle,
Matthew Garrett e681abd
+				EFI_LOCATE_BY_PROTOCOL, &pci_proto,
Matthew Garrett e681abd
+				NULL, &size, pci_handle);
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+	if (status == EFI_BUFFER_TOO_SMALL) {
Matthew Garrett e681abd
+		status = efi_call_phys3(sys_table->boottime->allocate_pool,
Matthew Garrett e681abd
+					EFI_LOADER_DATA, size, &pci_handle);
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		if (status != EFI_SUCCESS)
Matthew Garrett e681abd
+			return status;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		status = efi_call_phys5(sys_table->boottime->locate_handle,
Matthew Garrett e681abd
+					EFI_LOCATE_BY_PROTOCOL, &pci_proto,
Matthew Garrett e681abd
+					NULL, &size, pci_handle);
Matthew Garrett e681abd
+	}
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+	if (status != EFI_SUCCESS)
Matthew Garrett e681abd
+		goto free_handle;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+	nr_pci = size / sizeof(void *);
Matthew Garrett e681abd
+	for (i = 0; i < nr_pci; i++) {
Matthew Garrett e681abd
+		void *h = pci_handle[i];
Matthew Garrett e681abd
+		uint64_t attributes;
Matthew Garrett e681abd
+		struct pci_setup_rom *rom;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		status = efi_call_phys3(sys_table->boottime->handle_protocol,
Matthew Garrett e681abd
+					h, &pci_proto, &pci;;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		if (status != EFI_SUCCESS)
Matthew Garrett e681abd
+			continue;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		if (!pci)
Matthew Garrett e681abd
+			continue;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		status = efi_call_phys4(pci->attributes, pci,
Matthew Garrett e681abd
+					EfiPciIoAttributeOperationGet, 0,
Matthew Garrett e681abd
+					&attributes);
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		if (status != EFI_SUCCESS)
Matthew Garrett e681abd
+			continue;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)
Matthew Garrett e681abd
+			continue;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		if (!pci->romimage || !pci->romsize)
Matthew Garrett e681abd
+			continue;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		size = pci->romsize + sizeof(*rom);
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		status = efi_call_phys3(sys_table->boottime->allocate_pool,
Matthew Garrett e681abd
+				EFI_LOADER_DATA, size, &rom;;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		if (status != EFI_SUCCESS)
Matthew Garrett e681abd
+			continue;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		rom->data.type = SETUP_PCI;
Matthew Garrett e681abd
+		rom->data.len = size - sizeof(struct setup_data);
Matthew Garrett e681abd
+		rom->data.next = NULL;
Matthew Garrett e681abd
+		rom->pcilen = pci->romsize;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		status = efi_call_phys5(pci->pci.read, pci,
Matthew Garrett e681abd
+					EfiPciIoWidthUint16, PCI_VENDOR_ID,
Matthew Garrett e681abd
+					1, &(rom->vendor));
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		if (status != EFI_SUCCESS)
Matthew Garrett e681abd
+			goto free_struct;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		status = efi_call_phys5(pci->pci.read, pci,
Matthew Garrett e681abd
+					EfiPciIoWidthUint16, PCI_DEVICE_ID,
Matthew Garrett e681abd
+					1, &(rom->devid));
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		if (status != EFI_SUCCESS)
Matthew Garrett e681abd
+			goto free_struct;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		status = efi_call_phys5(pci->get_location, pci,
Matthew Garrett e681abd
+					&(rom->segment), &(rom->bus),
Matthew Garrett e681abd
+					&(rom->device), &(rom->function));
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		if (status != EFI_SUCCESS)
Matthew Garrett e681abd
+			goto free_struct;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		memcpy(rom->romdata, pci->romimage, pci->romsize);
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		if (data)
Matthew Garrett e681abd
+			data->next = (uint64_t)rom;
Matthew Garrett e681abd
+		else
Matthew Garrett e681abd
+			params->hdr.setup_data = (uint64_t)rom;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		data = (struct setup_data *)rom;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		continue;
Matthew Garrett e681abd
+	free_struct:
Matthew Garrett e681abd
+		efi_call_phys1(sys_table->boottime->free_pool, rom);
Matthew Garrett e681abd
+	}
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+free_handle:
Matthew Garrett e681abd
+	efi_call_phys1(sys_table->boottime->free_pool, pci_handle);
Matthew Garrett e681abd
+	return status;
Matthew Garrett e681abd
+}
Matthew Garrett e681abd
+
Matthew Garrett e681abd
 /*
Matthew Garrett e681abd
  * See if we have Graphics Output Protocol
Matthew Garrett e681abd
  */
Matthew Garrett e681abd
@@ -276,8 +392,9 @@
Matthew Garrett e681abd
 	nr_gops = size / sizeof(void *);
Matthew Garrett e681abd
 	for (i = 0; i < nr_gops; i++) {
Matthew Garrett e681abd
 		struct efi_graphics_output_mode_info *info;
Matthew Garrett e681abd
-		efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
Matthew Garrett e681abd
-		void *pciio;
Matthew Garrett e681abd
+		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
Matthew Garrett e681abd
+		bool conout_found = false;
Matthew Garrett e681abd
+		void *dummy;
Matthew Garrett e681abd
 		void *h = gop_handle[i];
Matthew Garrett e681abd
 
Matthew Garrett e681abd
 		status = efi_call_phys3(sys_table->boottime->handle_protocol,
Matthew Garrett e681abd
@@ -285,19 +402,21 @@
Matthew Garrett e681abd
 		if (status != EFI_SUCCESS)
Matthew Garrett e681abd
 			continue;
Matthew Garrett e681abd
 
Matthew Garrett e681abd
-		efi_call_phys3(sys_table->boottime->handle_protocol,
Matthew Garrett e681abd
-			       h, &pciio_proto, &pciio);
Matthew Garrett e681abd
+		status = efi_call_phys3(sys_table->boottime->handle_protocol,
Matthew Garrett e681abd
+					h, &conout_proto, &dummy);
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		if (status == EFI_SUCCESS)
Matthew Garrett e681abd
+			conout_found = true;
Matthew Garrett e681abd
 
Matthew Garrett e681abd
 		status = efi_call_phys4(gop->query_mode, gop,
Matthew Garrett e681abd
 					gop->mode->mode, &size, &info;;
Matthew Garrett e681abd
-		if (status == EFI_SUCCESS && (!first_gop || pciio)) {
Matthew Garrett e681abd
+		if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
Matthew Garrett e681abd
 			/*
Matthew Garrett e681abd
-			 * Apple provide GOPs that are not backed by
Matthew Garrett e681abd
-			 * real hardware (they're used to handle
Matthew Garrett e681abd
-			 * multiple displays). The workaround is to
Matthew Garrett e681abd
-			 * search for a GOP implementing the PCIIO
Matthew Garrett e681abd
-			 * protocol, and if one isn't found, to just
Matthew Garrett e681abd
-			 * fallback to the first GOP.
Matthew Garrett e681abd
+			 * Systems that use the UEFI Console Splitter may
Matthew Garrett e681abd
+			 * provide multiple GOP devices, not all of which are
Matthew Garrett e681abd
+			 * backed by real hardware. The workaround is to search
Matthew Garrett e681abd
+			 * for a GOP implementing the ConOut protocol, and if
Matthew Garrett e681abd
+			 * one isn't found, to just fall back to the first GOP.
Matthew Garrett e681abd
 			 */
Matthew Garrett e681abd
 			width = info->horizontal_resolution;
Matthew Garrett e681abd
 			height = info->vertical_resolution;
Matthew Garrett e681abd
@@ -308,10 +427,10 @@
Matthew Garrett e681abd
 			pixels_per_scan_line = info->pixels_per_scan_line;
Matthew Garrett e681abd
 
Matthew Garrett e681abd
 			/*
Matthew Garrett e681abd
-			 * Once we've found a GOP supporting PCIIO,
Matthew Garrett e681abd
+			 * Once we've found a GOP supporting ConOut,
Matthew Garrett e681abd
 			 * don't bother looking any further.
Matthew Garrett e681abd
 			 */
Matthew Garrett e681abd
-			if (pciio)
Matthew Garrett e681abd
+			if (conout_found)
Matthew Garrett e681abd
 				break;
Matthew Garrett e681abd
 
Matthew Garrett e681abd
 			first_gop = gop;
Matthew Garrett e681abd
@@ -1052,6 +1171,8 @@
Matthew Garrett e681abd
 
Matthew Garrett e681abd
 	setup_graphics(boot_params);
Matthew Garrett e681abd
 
Matthew Garrett e681abd
+	setup_efi_pci(boot_params);
Matthew Garrett e681abd
+
Matthew Garrett e681abd
 	status = efi_call_phys3(sys_table->boottime->allocate_pool,
Matthew Garrett e681abd
 				EFI_LOADER_DATA, sizeof(*gdt),
Matthew Garrett e681abd
 				(void **)&gdt;;
Matthew Garrett e681abd
diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.h
Matthew Garrett e681abd
--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.h	2012-07-21 16:58:29.000000000 -0400
Matthew Garrett e681abd
+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/boot/compressed/eboot.h	2012-08-22 15:25:40.530244882 -0400
Matthew Garrett e681abd
@@ -14,6 +14,10 @@
Matthew Garrett e681abd
 #define EFI_PAGE_SIZE		(1UL << EFI_PAGE_SHIFT)
Matthew Garrett e681abd
 #define EFI_READ_CHUNK_SIZE	(1024 * 1024)
Matthew Garrett e681abd
 
Matthew Garrett e681abd
+#define EFI_CONSOLE_OUT_DEVICE_GUID    \
Matthew Garrett e681abd
+	EFI_GUID( 0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, \
Matthew Garrett e681abd
+		  0x3f, 0xc1, 0x4d )
Matthew Garrett e681abd
+
Matthew Garrett e681abd
 #define PIXEL_RGB_RESERVED_8BIT_PER_COLOR		0
Matthew Garrett e681abd
 #define PIXEL_BGR_RESERVED_8BIT_PER_COLOR		1
Matthew Garrett e681abd
 #define PIXEL_BIT_MASK					2
Matthew Garrett e681abd
diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h
Matthew Garrett e681abd
--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h	2012-08-22 15:26:32.485522068 -0400
Matthew Garrett e681abd
+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/bootparam.h	2012-08-22 15:25:40.530244882 -0400
Matthew Garrett e681abd
@@ -13,6 +13,7 @@
Matthew Garrett e681abd
 #define SETUP_NONE			0
Matthew Garrett e681abd
 #define SETUP_E820_EXT			1
Matthew Garrett e681abd
 #define SETUP_DTB			2
Matthew Garrett e681abd
+#define SETUP_PCI			3
Matthew Garrett e681abd
 
Matthew Garrett e681abd
 /* extensible setup data list node */
Matthew Garrett e681abd
 struct setup_data {
Matthew Garrett e681abd
diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/pci.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/pci.h
Matthew Garrett e681abd
--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/pci.h	2012-07-21 16:58:29.000000000 -0400
Matthew Garrett e681abd
+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/include/asm/pci.h	2012-08-22 15:25:40.530244882 -0400
Matthew Garrett e681abd
@@ -171,4 +171,16 @@
Matthew Garrett e681abd
 }
Matthew Garrett e681abd
 #endif
Matthew Garrett e681abd
 
Matthew Garrett e681abd
+struct pci_setup_rom {
Matthew Garrett e681abd
+	struct setup_data data;
Matthew Garrett e681abd
+	uint16_t vendor;
Matthew Garrett e681abd
+	uint16_t devid;
Matthew Garrett e681abd
+	uint64_t pcilen;
Matthew Garrett e681abd
+	unsigned long segment;
Matthew Garrett e681abd
+	unsigned long bus;
Matthew Garrett e681abd
+	unsigned long device;
Matthew Garrett e681abd
+	unsigned long function;
Matthew Garrett e681abd
+	uint8_t romdata[0];
Matthew Garrett e681abd
+};
Matthew Garrett e681abd
+
Matthew Garrett e681abd
 #endif /* _ASM_X86_PCI_H */
Matthew Garrett e681abd
diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/pci/common.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/pci/common.c
Matthew Garrett e681abd
--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/pci/common.c	2012-08-22 15:24:45.477951182 -0400
Matthew Garrett e681abd
+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/arch/x86/pci/common.c	2012-08-22 15:25:40.530244882 -0400
Matthew Garrett e681abd
@@ -17,6 +17,7 @@
Matthew Garrett e681abd
 #include <asm/io.h>
Matthew Garrett e681abd
 #include <asm/smp.h>
Matthew Garrett e681abd
 #include <asm/pci_x86.h>
Matthew Garrett e681abd
+#include <asm/setup.h>
Matthew Garrett e681abd
 
Matthew Garrett e681abd
 unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
Matthew Garrett e681abd
 				PCI_PROBE_MMCONF;
Matthew Garrett e681abd
@@ -608,6 +609,38 @@
Matthew Garrett e681abd
 	return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
Matthew Garrett e681abd
 }
Matthew Garrett e681abd
 
Matthew Garrett e681abd
+int pcibios_add_device(struct pci_dev *dev)
Matthew Garrett e681abd
+{
Matthew Garrett e681abd
+	struct setup_data *data;
Matthew Garrett e681abd
+	struct pci_setup_rom *rom;
Matthew Garrett e681abd
+	u64 pa_data;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+	if (boot_params.hdr.version < 0x0209)
Matthew Garrett e681abd
+		return 0;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+	pa_data = boot_params.hdr.setup_data;
Matthew Garrett e681abd
+	while (pa_data) {
Matthew Garrett e681abd
+		data = phys_to_virt(pa_data);
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+		if (data->type == SETUP_PCI) {
Matthew Garrett e681abd
+			rom = (struct pci_setup_rom *)data;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+			if ((pci_domain_nr(dev->bus) == rom->segment) &&
Matthew Garrett e681abd
+			    (dev->bus->number == rom->bus) &&
Matthew Garrett e681abd
+			    (PCI_SLOT(dev->devfn) == rom->device) &&
Matthew Garrett e681abd
+			    (PCI_FUNC(dev->devfn) == rom->function) &&
Matthew Garrett e681abd
+			    (dev->vendor == rom->vendor) &&
Matthew Garrett e681abd
+			    (dev->device == rom->devid)) {
Matthew Garrett e681abd
+				dev->rom = (void *)(pa_data +
Matthew Garrett e681abd
+				      offsetof(struct pci_setup_rom, romdata));
Matthew Garrett e681abd
+				dev->romlen = rom->pcilen;
Matthew Garrett e681abd
+			}
Matthew Garrett e681abd
+		}
Matthew Garrett e681abd
+		pa_data = data->next;
Matthew Garrett e681abd
+	}
Matthew Garrett e681abd
+	return 0;
Matthew Garrett e681abd
+}
Matthew Garrett e681abd
+
Matthew Garrett e681abd
 int pcibios_enable_device(struct pci_dev *dev, int mask)
Matthew Garrett e681abd
 {
Matthew Garrett e681abd
 	int err;
Matthew Garrett e681abd
diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/bus.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/bus.c
Matthew Garrett e681abd
--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/bus.c	2012-08-22 15:24:47.425961575 -0400
Matthew Garrett e681abd
+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/bus.c	2012-08-22 15:26:20.147456241 -0400
Matthew Garrett e681abd
@@ -166,6 +166,11 @@
Matthew Garrett e681abd
 	int retval;
Matthew Garrett e681abd
 
Matthew Garrett e681abd
 	pci_fixup_device(pci_fixup_final, dev);
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+	retval = pcibios_add_device(dev);
Matthew Garrett e681abd
+	if (retval)
Matthew Garrett e681abd
+		return retval;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
 	retval = device_add(&dev->dev);
Matthew Garrett e681abd
 	if (retval)
Matthew Garrett e681abd
 		return retval;
Matthew Garrett e681abd
diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/pci.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/pci.c
Matthew Garrett e681abd
--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/pci.c	2012-08-22 15:24:47.432961612 -0400
Matthew Garrett e681abd
+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/pci.c	2012-08-22 15:25:40.531244893 -0400
Matthew Garrett e681abd
@@ -1385,6 +1385,19 @@
Matthew Garrett e681abd
 		dr->pinned = 1;
Matthew Garrett e681abd
 }
Matthew Garrett e681abd
 
Matthew Garrett e681abd
+/*
Matthew Garrett e681abd
+ * pcibios_add_device - provide arch specific hooks when adding device dev
Matthew Garrett e681abd
+ * @dev: the PCI device being added
Matthew Garrett e681abd
+ *
Matthew Garrett e681abd
+ * Permits the platform to provide architecture specific functionality when
Matthew Garrett e681abd
+ * devices are added. This is the default implementation. Architecture
Matthew Garrett e681abd
+ * implementations can override this.
Matthew Garrett e681abd
+ */
Matthew Garrett e681abd
+int __attribute__ ((weak)) pcibios_add_device (struct pci_dev *dev)
Matthew Garrett e681abd
+{
Matthew Garrett e681abd
+	return 0;
Matthew Garrett e681abd
+}
Matthew Garrett e681abd
+
Matthew Garrett e681abd
 /**
Matthew Garrett e681abd
  * pcibios_disable_device - disable arch specific PCI resources for device dev
Matthew Garrett e681abd
  * @dev: the PCI device to disable
Matthew Garrett e681abd
diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c
Matthew Garrett e681abd
--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c	2012-07-21 16:58:29.000000000 -0400
Matthew Garrett e681abd
+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/drivers/pci/rom.c	2012-08-22 15:25:40.531244893 -0400
David Woodhouse 61db236
@@ -118,11 +118,17 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
David Woodhouse 61db236
 	void __iomem *rom;
David Woodhouse 61db236
 
David Woodhouse 61db236
 	/*
Matthew Garrett e681abd
+	 * Some devices may provide ROMs via a source other than the BAR
Matthew Garrett e681abd
+	 */
David Woodhouse 61db236
+	if (pdev->rom && pdev->romlen) {
Matthew Garrett e681abd
+		*size = pdev->romlen;
Matthew Garrett e681abd
+		return phys_to_virt(pdev->rom);
David Woodhouse 61db236
+	/*
David Woodhouse 61db236
 	 * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy
David Woodhouse 61db236
 	 * memory map if the VGA enable bit of the Bridge Control register is
David Woodhouse 61db236
 	 * set for embedded VGA.
David Woodhouse 61db236
 	 */
David Woodhouse 61db236
-	if (res->flags & IORESOURCE_ROM_SHADOW) {
David Woodhouse 61db236
+	} else if (res->flags & IORESOURCE_ROM_SHADOW) {
David Woodhouse 61db236
 		/* primary video rom always starts here */
David Woodhouse 61db236
 		start = (loff_t)0xC0000;
David Woodhouse 61db236
 		*size = 0x20000; /* cover C000:0 through E000:0 */
Matthew Garrett e681abd
@@ -219,7 +225,8 @@
Matthew Garrett e681abd
 	if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
Matthew Garrett e681abd
 		return;
Matthew Garrett e681abd
 
Matthew Garrett e681abd
-	iounmap(rom);
Matthew Garrett e681abd
+	if (!pdev->rom || !pdev->romlen)
Matthew Garrett e681abd
+		iounmap(rom);
Matthew Garrett e681abd
 
Matthew Garrett e681abd
 	/* Disable again before continuing, leave enabled if pci=rom */
Matthew Garrett e681abd
 	if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW)))
Matthew Garrett e681abd
diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/efi.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/efi.h
Matthew Garrett e681abd
--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/efi.h	2012-08-22 15:24:49.550972911 -0400
Matthew Garrett e681abd
+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/efi.h	2012-08-22 15:25:40.533244906 -0400
Matthew Garrett e681abd
@@ -196,6 +196,77 @@
Matthew Garrett e681abd
 	void *create_event_ex;
Matthew Garrett e681abd
 } efi_boot_services_t;
Matthew Garrett e681abd
 
Matthew Garrett e681abd
+typedef enum {
Matthew Garrett e681abd
+	EfiPciIoWidthUint8,
Matthew Garrett e681abd
+	EfiPciIoWidthUint16,
Matthew Garrett e681abd
+	EfiPciIoWidthUint32,
Matthew Garrett e681abd
+	EfiPciIoWidthUint64,
Matthew Garrett e681abd
+	EfiPciIoWidthFifoUint8,
Matthew Garrett e681abd
+	EfiPciIoWidthFifoUint16,
Matthew Garrett e681abd
+	EfiPciIoWidthFifoUint32,
Matthew Garrett e681abd
+	EfiPciIoWidthFifoUint64,
Matthew Garrett e681abd
+	EfiPciIoWidthFillUint8,
Matthew Garrett e681abd
+	EfiPciIoWidthFillUint16,
Matthew Garrett e681abd
+	EfiPciIoWidthFillUint32,
Matthew Garrett e681abd
+	EfiPciIoWidthFillUint64,
Matthew Garrett e681abd
+	EfiPciIoWidthMaximum
Matthew Garrett e681abd
+} EFI_PCI_IO_PROTOCOL_WIDTH;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+typedef enum {
Matthew Garrett e681abd
+	EfiPciIoAttributeOperationGet,
Matthew Garrett e681abd
+	EfiPciIoAttributeOperationSet,
Matthew Garrett e681abd
+	EfiPciIoAttributeOperationEnable,
Matthew Garrett e681abd
+	EfiPciIoAttributeOperationDisable,
Matthew Garrett e681abd
+	EfiPciIoAttributeOperationSupported,
Matthew Garrett e681abd
+    EfiPciIoAttributeOperationMaximum
Matthew Garrett e681abd
+} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+typedef struct {
Matthew Garrett e681abd
+	void *read;
Matthew Garrett e681abd
+	void *write;
Matthew Garrett e681abd
+} efi_pci_io_protocol_access_t;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+typedef struct {
Matthew Garrett e681abd
+	void *poll_mem;
Matthew Garrett e681abd
+	void *poll_io;
Matthew Garrett e681abd
+	efi_pci_io_protocol_access_t mem;
Matthew Garrett e681abd
+	efi_pci_io_protocol_access_t io;
Matthew Garrett e681abd
+	efi_pci_io_protocol_access_t pci;
Matthew Garrett e681abd
+	void *copy_mem;
Matthew Garrett e681abd
+	void *map;
Matthew Garrett e681abd
+	void *unmap;
Matthew Garrett e681abd
+	void *allocate_buffer;
Matthew Garrett e681abd
+	void *free_buffer;
Matthew Garrett e681abd
+	void *flush;
Matthew Garrett e681abd
+	void *get_location;
Matthew Garrett e681abd
+	void *attributes;
Matthew Garrett e681abd
+	void *get_bar_attributes;
Matthew Garrett e681abd
+	void *set_bar_attributes;
Matthew Garrett e681abd
+	uint64_t romsize;
Matthew Garrett e681abd
+	void *romimage;
Matthew Garrett e681abd
+} efi_pci_io_protocol;
Matthew Garrett e681abd
+
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO 0x0004
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY 0x0008
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_VGA_IO 0x0010
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO 0x0020
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO 0x0040
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_IO 0x0100
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY 0x0200
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER 0x0400
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED 0x0800
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE 0x2000
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM 0x4000
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 0x10000
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000
Matthew Garrett e681abd
+#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000
Matthew Garrett e681abd
+
Matthew Garrett e681abd
 /*
Matthew Garrett e681abd
  * Types and defines for EFI ResetSystem
Matthew Garrett e681abd
  */
Matthew Garrett e681abd
diff -ur linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/pci.h ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/pci.h
Matthew Garrett e681abd
--- linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/pci.h	2012-08-22 15:24:48.703968392 -0400
Matthew Garrett e681abd
+++ ../kernel-3.5.fc18.bak/linux-3.6.0-0.rc2.git2.1.fc18.x86_64/include/linux/pci.h	2012-08-22 15:25:40.534244910 -0400
Matthew Garrett e681abd
@@ -355,6 +355,8 @@
Matthew Garrett e681abd
 	};
Matthew Garrett e681abd
 	struct pci_ats	*ats;	/* Address Translation Service */
Matthew Garrett e681abd
 #endif
Matthew Garrett e681abd
+	void *rom; /* Physical pointer to ROM if it's not from the BAR */
Matthew Garrett e681abd
+	size_t romlen; /* Length of ROM if it's not from the BAR */
Matthew Garrett e681abd
 };
Matthew Garrett e681abd
 
Matthew Garrett e681abd
 static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
Matthew Garrett e681abd
@@ -1582,6 +1584,7 @@
Matthew Garrett e681abd
 void pcibios_set_master(struct pci_dev *dev);
Matthew Garrett e681abd
 int pcibios_set_pcie_reset_state(struct pci_dev *dev,
Matthew Garrett e681abd
 				 enum pcie_reset_state state);
Matthew Garrett e681abd
+int pcibios_add_device(struct pci_dev *dev);
Matthew Garrett e681abd
 
Matthew Garrett e681abd
 #ifdef CONFIG_PCI_MMCONFIG
Matthew Garrett e681abd
 extern void __init pci_mmcfg_early_init(void);