1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /* This file is part of the coreboot project. */
4 #include <console/console.h>
5 #include <commonlib/endian.h>
6 #include <device/device.h>
7 #include <device/pci.h>
8 #include <device/pci_ids.h>
9 #include <device/pci_ops.h>
13 #include <acpi/acpigen.h>
15 /* Rmodules don't like weak symbols. */
16 void __weak
map_oprom_vendev_rev(u32
*vendev
, u8
*rev
) { return; }
17 u32 __weak
map_oprom_vendev(u32 vendev
) { return vendev
; }
19 struct rom_header
*pci_rom_probe(const struct device
*dev
)
21 struct rom_header
*rom_header
= NULL
;
22 struct pci_data
*rom_data
;
23 u8 rev
= pci_read_config8(dev
, PCI_REVISION_ID
);
25 u32 vendev
= (dev
->vendor
<< 16) | dev
->device
;
26 u32 mapped_vendev
= vendev
;
28 /* If the ROM is in flash, then don't check the PCI device for it. */
29 if (CONFIG(CHECK_REV_IN_OPROM_NAME
)) {
30 rom_header
= cbfs_boot_map_optionrom_revision(dev
->vendor
, dev
->device
, rev
);
31 map_oprom_vendev_rev(&mapped_vendev
, &mapped_rev
);
33 rom_header
= cbfs_boot_map_optionrom(dev
->vendor
, dev
->device
);
34 mapped_vendev
= map_oprom_vendev(vendev
);
38 if (CONFIG(CHECK_REV_IN_OPROM_NAME
) &&
39 (vendev
!= mapped_vendev
|| rev
!= mapped_rev
)) {
40 rom_header
= cbfs_boot_map_optionrom_revision(
42 mapped_vendev
& 0xffff, mapped_rev
);
43 } else if (vendev
!= mapped_vendev
) {
44 rom_header
= cbfs_boot_map_optionrom(
46 mapped_vendev
& 0xffff);
51 printk(BIOS_DEBUG
, "In CBFS, ROM address for %s = %p\n",
52 dev_path(dev
), rom_header
);
53 } else if (!CONFIG(ON_DEVICE_ROM_LOAD
)) {
54 printk(BIOS_DEBUG
, "PCI Option ROM loading disabled for %s\n",
58 uintptr_t rom_address
;
60 rom_address
= pci_read_config32(dev
, PCI_ROM_ADDRESS
);
62 if (rom_address
== 0x00000000 || rom_address
== 0xffffffff) {
63 #if CONFIG(CPU_QEMU_X86)
64 if ((dev
->class >> 8) == PCI_CLASS_DISPLAY_VGA
)
65 rom_address
= 0xc0000;
70 /* Enable expansion ROM address decoding. */
71 pci_write_config32(dev
, PCI_ROM_ADDRESS
,
72 rom_address
|PCI_ROM_ADDRESS_ENABLE
);
75 rom_address
&= PCI_ROM_ADDRESS_MASK
;
77 printk(BIOS_DEBUG
, "Option ROM address for %s = %lx\n",
78 dev_path(dev
), (unsigned long)rom_address
);
79 rom_header
= (struct rom_header
*)rom_address
;
82 printk(BIOS_SPEW
, "PCI expansion ROM, signature 0x%04x, "
83 "INIT size 0x%04x, data ptr 0x%04x\n",
84 le32_to_cpu(rom_header
->signature
),
85 rom_header
->size
* 512, le32_to_cpu(rom_header
->data
));
87 if (le32_to_cpu(rom_header
->signature
) != PCI_ROM_HDR
) {
88 printk(BIOS_ERR
, "Incorrect expansion ROM header "
89 "signature %04x\n", le32_to_cpu(rom_header
->signature
));
93 rom_data
= (((void *)rom_header
) + le32_to_cpu(rom_header
->data
));
95 printk(BIOS_SPEW
, "PCI ROM image, vendor ID %04x, device ID %04x,\n",
96 rom_data
->vendor
, rom_data
->device
);
97 /* If the device id is mapped, a mismatch is expected */
98 if ((dev
->vendor
!= rom_data
->vendor
99 || dev
->device
!= rom_data
->device
)
100 && (vendev
== mapped_vendev
)) {
101 printk(BIOS_ERR
, "ID mismatch: vendor ID %04x, "
102 "device ID %04x\n", dev
->vendor
, dev
->device
);
106 printk(BIOS_SPEW
, "PCI ROM image, Class Code %04x%02x, "
107 "Code Type %02x\n", rom_data
->class_hi
, rom_data
->class_lo
,
110 if (dev
->class != ((rom_data
->class_hi
<< 8) | rom_data
->class_lo
)) {
111 printk(BIOS_DEBUG
, "Class Code mismatch ROM %08x, dev %08x\n",
112 (rom_data
->class_hi
<< 8) | rom_data
->class_lo
,
120 static void *pci_ram_image_start
= (void *)PCI_RAM_IMAGE_START
;
122 struct rom_header
*pci_rom_load(struct device
*dev
,
123 struct rom_header
*rom_header
)
125 struct pci_data
* rom_data
;
126 unsigned int rom_size
;
127 unsigned int image_size
=0;
130 /* Get next image. */
131 rom_header
= (struct rom_header
*)((void *) rom_header
134 rom_data
= (struct pci_data
*)((void *) rom_header
135 + le32_to_cpu(rom_header
->data
));
137 image_size
= le32_to_cpu(rom_data
->ilen
) * 512;
138 } while ((rom_data
->type
!= 0) && (rom_data
->indicator
!= 0)); // make sure we got x86 version
140 if (rom_data
->type
!= 0)
143 rom_size
= rom_header
->size
* 512;
146 * We check to see if the device thinks it is a VGA device not
147 * whether the ROM image is for a VGA device because some
148 * devices have a mismatch between the hardware and the ROM.
150 if ((dev
->class >> 8) == PCI_CLASS_DISPLAY_VGA
) {
151 #if !CONFIG(MULTIPLE_VGA_ADAPTERS)
152 extern struct device
*vga_pri
; /* Primary VGA device (device.c). */
153 if (dev
!= vga_pri
) return NULL
; /* Only one VGA supported. */
155 if ((void *)PCI_VGA_RAM_IMAGE_START
!= rom_header
) {
156 printk(BIOS_DEBUG
, "Copying VGA ROM Image from %p to "
157 "0x%x, 0x%x bytes\n", rom_header
,
158 PCI_VGA_RAM_IMAGE_START
, rom_size
);
159 memcpy((void *)PCI_VGA_RAM_IMAGE_START
, rom_header
,
162 return (struct rom_header
*) (PCI_VGA_RAM_IMAGE_START
);
165 printk(BIOS_DEBUG
, "Copying non-VGA ROM image from %p to %p, 0x%x "
166 "bytes\n", rom_header
, pci_ram_image_start
, rom_size
);
168 memcpy(pci_ram_image_start
, rom_header
, rom_size
);
169 pci_ram_image_start
+= rom_size
;
170 return (struct rom_header
*) (pci_ram_image_start
-rom_size
);
174 #if CONFIG(HAVE_ACPI_TABLES)
176 /* VBIOS may be modified after oprom init so use the copy if present. */
177 static struct rom_header
*check_initialized(const struct device
*dev
)
179 struct rom_header
*run_rom
;
180 struct pci_data
*rom_data
;
182 if (!CONFIG(VGA_ROM_RUN
))
185 run_rom
= (struct rom_header
*)(uintptr_t)PCI_VGA_RAM_IMAGE_START
;
186 if (read_le16(&run_rom
->signature
) != PCI_ROM_HDR
)
189 rom_data
= (struct pci_data
*)((u8
*)run_rom
190 + read_le16(&run_rom
->data
));
192 if (read_le32(&rom_data
->signature
) == PCI_DATA_HDR
193 && read_le16(&rom_data
->device
) == dev
->device
194 && read_le16(&rom_data
->vendor
) == dev
->vendor
)
201 pci_rom_acpi_fill_vfct(const struct device
*device
, acpi_vfct_t
*vfct_struct
,
202 unsigned long current
)
204 acpi_vfct_image_hdr_t
*header
= &vfct_struct
->image_hdr
;
205 struct rom_header
*rom
;
207 rom
= check_initialized(device
);
209 rom
= pci_rom_probe(device
);
211 printk(BIOS_ERR
, "pci_rom_acpi_fill_vfct failed\n");
215 printk(BIOS_DEBUG
, " Copying %sVBIOS image from %p\n",
216 rom
== (struct rom_header
*)
217 (uintptr_t)PCI_VGA_RAM_IMAGE_START
?
221 header
->DeviceID
= device
->device
;
222 header
->VendorID
= device
->vendor
;
223 header
->PCIBus
= device
->bus
->secondary
;
224 header
->PCIFunction
= PCI_FUNC(device
->path
.pci
.devfn
);
225 header
->PCIDevice
= PCI_SLOT(device
->path
.pci
.devfn
);
226 header
->ImageLength
= rom
->size
* 512;
227 memcpy((void *)&header
->VbiosContent
, rom
, header
->ImageLength
);
229 vfct_struct
->VBIOSImageOffset
= (size_t)header
- (size_t)vfct_struct
;
231 current
+= header
->ImageLength
;
236 pci_rom_write_acpi_tables(const struct device
*device
, unsigned long current
,
237 struct acpi_rsdp
*rsdp
)
239 /* Only handle VGA devices */
240 if ((device
->class >> 8) != PCI_CLASS_DISPLAY_VGA
)
243 /* Only handle enabled devices */
244 if (!device
->enabled
)
247 /* AMD/ATI uses VFCT */
248 if (device
->vendor
== PCI_VENDOR_ID_ATI
) {
251 current
= ALIGN_UP(current
, 8);
252 vfct
= (acpi_vfct_t
*)current
;
253 acpi_create_vfct(device
, vfct
, pci_rom_acpi_fill_vfct
);
254 if (vfct
->header
.length
) {
255 printk(BIOS_DEBUG
, "ACPI: * VFCT at %lx\n", current
);
256 current
+= vfct
->header
.length
;
257 acpi_add_table(rsdp
, vfct
);
264 void pci_rom_ssdt(const struct device
*device
)
268 /* Only handle VGA devices */
269 if ((device
->class >> 8) != PCI_CLASS_DISPLAY_VGA
)
272 /* Only handle enabled devices */
273 if (!device
->enabled
)
276 /* Probe for option rom */
277 const struct rom_header
*rom
= pci_rom_probe(device
);
278 if (!rom
|| !rom
->size
) {
279 printk(BIOS_WARNING
, "%s: Missing PCI Option ROM\n",
284 const char *scope
= acpi_device_path(device
);
286 printk(BIOS_ERR
, "%s: Missing ACPI scope\n", dev_path(device
));
290 /* Supports up to four devices. */
291 if ((CBMEM_ID_ROM0
+ ngfx
) > CBMEM_ID_ROM3
) {
292 printk(BIOS_ERR
, "%s: Out of CBMEM IDs.\n", dev_path(device
));
297 const size_t cbrom_length
= rom
->size
* 512;
299 printk(BIOS_ERR
, "%s: ROM has zero length!\n",
304 void *cbrom
= cbmem_add(CBMEM_ID_ROM0
+ ngfx
, cbrom_length
);
306 printk(BIOS_ERR
, "%s: Failed to allocate CBMEM.\n",
310 /* Increment CBMEM id for next device */
313 memcpy(cbrom
, rom
, cbrom_length
);
315 /* write _ROM method */
316 acpigen_write_scope(scope
);
317 acpigen_write_rom(cbrom
, cbrom_length
);
318 acpigen_pop_len(); /* pop scope */