2 * This file is part of the coreboot project.
4 * Copyright (C) 2005 Li-Ta Lo <ollie@lanl.gov>
5 * Copyright (C) 2005 Tyan
6 * (Written by Yinghai Lu <yhlu@tyan.com> for Tyan)
7 * Copyright (C) 2005 Ronald G. Minnich <rminnich@gmail.com>
8 * Copyright (C) 2005-2007 Stefan Reinauer <stepan@openbios.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2 of the License.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
20 #include <console/console.h>
21 #include <commonlib/endian.h>
23 #include <device/device.h>
24 #include <device/pci.h>
25 #include <device/pci_ids.h>
26 #include <device/pci_ops.h>
30 #include <arch/acpigen.h>
32 /* Rmodules don't like weak symbols. */
33 u32 __weak
map_oprom_vendev(u32 vendev
) { return vendev
; }
35 struct rom_header
*pci_rom_probe(struct device
*dev
)
37 struct rom_header
*rom_header
;
38 struct pci_data
*rom_data
;
40 /* If it's in FLASH, then don't check device for ROM. */
41 rom_header
= cbfs_boot_map_optionrom(dev
->vendor
, dev
->device
);
43 u32 vendev
= (dev
->vendor
<< 16) | dev
->device
;
46 mapped_vendev
= map_oprom_vendev(vendev
);
49 if (vendev
!= mapped_vendev
) {
50 rom_header
= cbfs_boot_map_optionrom(
52 mapped_vendev
& 0xffff);
57 printk(BIOS_DEBUG
, "In CBFS, ROM address for %s = %p\n",
58 dev_path(dev
), rom_header
);
59 } else if (!IS_ENABLED(CONFIG_ON_DEVICE_ROM_LOAD
)) {
60 printk(BIOS_DEBUG
, "PCI Option ROM loading disabled "
61 "for %s\n", dev_path(dev
));
64 uintptr_t rom_address
;
66 rom_address
= pci_read_config32(dev
, PCI_ROM_ADDRESS
);
68 if (rom_address
== 0x00000000 || rom_address
== 0xffffffff) {
69 #if IS_ENABLED(CONFIG_BOARD_EMULATION_QEMU_X86)
70 if ((dev
->class >> 8) == PCI_CLASS_DISPLAY_VGA
)
71 rom_address
= 0xc0000;
76 /* Enable expansion ROM address decoding. */
77 pci_write_config32(dev
, PCI_ROM_ADDRESS
,
78 rom_address
|PCI_ROM_ADDRESS_ENABLE
);
81 printk(BIOS_DEBUG
, "Option ROM address for %s = %lx\n",
82 dev_path(dev
), (unsigned long)rom_address
);
83 rom_header
= (struct rom_header
*)rom_address
;
86 printk(BIOS_SPEW
, "PCI expansion ROM, signature 0x%04x, "
87 "INIT size 0x%04x, data ptr 0x%04x\n",
88 le32_to_cpu(rom_header
->signature
),
89 rom_header
->size
* 512, le32_to_cpu(rom_header
->data
));
91 if (le32_to_cpu(rom_header
->signature
) != PCI_ROM_HDR
) {
92 printk(BIOS_ERR
, "Incorrect expansion ROM header "
93 "signature %04x\n", le32_to_cpu(rom_header
->signature
));
97 rom_data
= (((void *)rom_header
) + le32_to_cpu(rom_header
->data
));
99 printk(BIOS_SPEW
, "PCI ROM image, vendor ID %04x, device ID %04x,\n",
100 rom_data
->vendor
, rom_data
->device
);
101 /* If the device id is mapped, a mismatch is expected */
102 if ((dev
->vendor
!= rom_data
->vendor
103 || dev
->device
!= rom_data
->device
)
104 && (vendev
== mapped_vendev
)) {
105 printk(BIOS_ERR
, "ID mismatch: vendor ID %04x, "
106 "device ID %04x\n", rom_data
->vendor
, rom_data
->device
);
110 printk(BIOS_SPEW
, "PCI ROM image, Class Code %04x%02x, "
111 "Code Type %02x\n", rom_data
->class_hi
, rom_data
->class_lo
,
114 if (dev
->class != ((rom_data
->class_hi
<< 8) | rom_data
->class_lo
)) {
115 printk(BIOS_DEBUG
, "Class Code mismatch ROM %08x, dev %08x\n",
116 (rom_data
->class_hi
<< 8) | rom_data
->class_lo
,
124 static void *pci_ram_image_start
= (void *)PCI_RAM_IMAGE_START
;
126 struct rom_header
*pci_rom_load(struct device
*dev
,
127 struct rom_header
*rom_header
)
129 struct pci_data
* rom_data
;
130 unsigned int rom_size
;
131 unsigned int image_size
=0;
134 /* Get next image. */
135 rom_header
= (struct rom_header
*)((void *) rom_header
138 rom_data
= (struct pci_data
*)((void *) rom_header
139 + le32_to_cpu(rom_header
->data
));
141 image_size
= le32_to_cpu(rom_data
->ilen
) * 512;
142 } while ((rom_data
->type
!= 0) && (rom_data
->indicator
!= 0)); // make sure we got x86 version
144 if (rom_data
->type
!= 0)
147 rom_size
= rom_header
->size
* 512;
150 * We check to see if the device thinks it is a VGA device not
151 * whether the ROM image is for a VGA device because some
152 * devices have a mismatch between the hardware and the ROM.
154 if (PCI_CLASS_DISPLAY_VGA
== (dev
->class >> 8)) {
155 #if !IS_ENABLED(CONFIG_MULTIPLE_VGA_ADAPTERS)
156 extern struct device
*vga_pri
; /* Primary VGA device (device.c). */
157 if (dev
!= vga_pri
) return NULL
; /* Only one VGA supported. */
159 if ((void *)PCI_VGA_RAM_IMAGE_START
!= rom_header
) {
160 printk(BIOS_DEBUG
, "Copying VGA ROM Image from %p to "
161 "0x%x, 0x%x bytes\n", rom_header
,
162 PCI_VGA_RAM_IMAGE_START
, rom_size
);
163 memcpy((void *)PCI_VGA_RAM_IMAGE_START
, rom_header
,
166 return (struct rom_header
*) (PCI_VGA_RAM_IMAGE_START
);
169 printk(BIOS_DEBUG
, "Copying non-VGA ROM image from %p to %p, 0x%x "
170 "bytes\n", rom_header
, pci_ram_image_start
, rom_size
);
172 memcpy(pci_ram_image_start
, rom_header
, rom_size
);
173 pci_ram_image_start
+= rom_size
;
174 return (struct rom_header
*) (pci_ram_image_start
-rom_size
);
178 #if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
180 /* VBIOS may be modified after oprom init so use the copy if present. */
181 static struct rom_header
*check_initialized(struct device
*dev
)
183 struct rom_header
*run_rom
;
184 struct pci_data
*rom_data
;
186 if (!IS_ENABLED(CONFIG_VGA_ROM_RUN
))
189 run_rom
= (struct rom_header
*)(uintptr_t)PCI_VGA_RAM_IMAGE_START
;
190 if (read_le16(&run_rom
->signature
) != PCI_ROM_HDR
)
193 rom_data
= (struct pci_data
*)((u8
*)run_rom
194 + read_le32(&run_rom
->data
));
196 if (read_le32(&rom_data
->signature
) == PCI_DATA_HDR
197 && read_le16(&rom_data
->device
) == dev
->device
198 && read_le16(&rom_data
->vendor
) == dev
->vendor
)
205 pci_rom_acpi_fill_vfct(struct device
*device
, struct acpi_vfct
*vfct_struct
,
206 unsigned long current
)
208 struct acpi_vfct_image_hdr
*header
= &vfct_struct
->image_hdr
;
209 struct rom_header
*rom
;
211 vfct_struct
->VBIOSImageOffset
= (size_t)header
- (size_t)vfct_struct
;
213 rom
= check_initialized(device
);
215 rom
= pci_rom_probe(device
);
217 printk(BIOS_ERR
, "pci_rom_acpi_fill_vfct failed\n");
221 printk(BIOS_DEBUG
, " Copying %sVBIOS image from %p\n",
222 rom
== (struct rom_header
*)
223 (uintptr_t)PCI_VGA_RAM_IMAGE_START
?
227 header
->DeviceID
= device
->device
;
228 header
->VendorID
= device
->vendor
;
229 header
->PCIBus
= device
->bus
->secondary
;
230 header
->PCIFunction
= PCI_FUNC(device
->path
.pci
.devfn
);
231 header
->PCIDevice
= PCI_SLOT(device
->path
.pci
.devfn
);
232 header
->ImageLength
= rom
->size
* 512;
233 memcpy((void *)&header
->VbiosContent
, rom
, header
->ImageLength
);
235 current
+= header
->ImageLength
;
240 pci_rom_write_acpi_tables(struct device
*device
, unsigned long current
,
241 struct acpi_rsdp
*rsdp
)
243 struct acpi_vfct
*vfct
;
244 struct rom_header
*rom
;
246 /* Only handle VGA devices */
247 if ((device
->class >> 8) != PCI_CLASS_DISPLAY_VGA
)
250 /* Only handle enabled devices */
251 if (!device
->enabled
)
254 /* Probe for option rom */
255 rom
= pci_rom_probe(device
);
259 /* AMD/ATI uses VFCT */
260 if (device
->vendor
== PCI_VENDOR_ID_ATI
) {
261 current
= ALIGN(current
, 8);
262 printk(BIOS_DEBUG
, "ACPI: * VFCT at %lx\n", current
);
263 vfct
= (struct acpi_vfct
*)current
;
264 acpi_create_vfct(device
, vfct
, pci_rom_acpi_fill_vfct
);
265 current
+= vfct
->header
.length
;
266 acpi_add_table(rsdp
, vfct
);
272 void pci_rom_ssdt(struct device
*device
)
276 /* Only handle VGA devices */
277 if ((device
->class >> 8) != PCI_CLASS_DISPLAY_VGA
)
280 /* Only handle enabled devices */
281 if (!device
->enabled
)
284 /* Probe for option rom */
285 const struct rom_header
*rom
= pci_rom_probe(device
);
286 if (!rom
|| !rom
->size
) {
287 printk(BIOS_WARNING
, "%s: Missing PCI Option ROM\n",
292 const char *scope
= acpi_device_path(device
);
294 printk(BIOS_ERR
, "%s: Missing ACPI scope\n", dev_path(device
));
298 /* Supports up to four devices. */
299 if ((CBMEM_ID_ROM0
+ ngfx
) > CBMEM_ID_ROM3
) {
300 printk(BIOS_ERR
, "%s: Out of CBMEM IDs.\n", dev_path(device
));
305 const size_t cbrom_length
= rom
->size
* 512;
307 printk(BIOS_ERR
, "%s: ROM has zero length!\n",
312 void *cbrom
= cbmem_add(CBMEM_ID_ROM0
+ ngfx
, cbrom_length
);
314 printk(BIOS_ERR
, "%s: Failed to allocate CBMEM.\n",
318 /* Increment CBMEM id for next device */
321 memcpy(cbrom
, rom
, cbrom_length
);
323 /* write _ROM method */
324 acpigen_write_scope(scope
);
325 acpigen_write_rom(cbrom
, cbrom_length
);
326 acpigen_pop_len(); /* pop scope */