xref: /aosp_15_r20/external/coreboot/src/device/pci_rom.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <commonlib/endian.h>
5 #include <device/device.h>
6 #include <device/pci.h>
7 #include <device/pci_ids.h>
8 #include <device/pci_ops.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <cbfs.h>
12 #include <cbmem.h>
13 #include <acpi/acpigen.h>
14 
15 /* Rmodules don't like weak symbols. */
map_oprom_vendev(u32 vendev)16 u32 __weak map_oprom_vendev(u32 vendev) { return vendev; }
17 
vga_oprom_preload(void)18 void vga_oprom_preload(void)
19 {
20 /* The CONFIG_VGA_BIOS_ID symbol is only defined when VGA_BIOS is selected */
21 #if CONFIG(VGA_BIOS)
22 	const char name[] = "pci" CONFIG_VGA_BIOS_ID ".rom";
23 
24 	if (!CONFIG(CBFS_PRELOAD))
25 		return;
26 
27 	printk(BIOS_DEBUG, "Preloading VGA ROM %s\n", name);
28 
29 	cbfs_preload(name);
30 #endif
31 }
32 
cbfs_boot_map_optionrom(uint16_t vendor,uint16_t device)33 static void *cbfs_boot_map_optionrom(uint16_t vendor, uint16_t device)
34 {
35 	char name[17] = "pciXXXX,XXXX.rom";
36 
37 	snprintf(name, sizeof(name), "pci%04hx,%04hx.rom", vendor, device);
38 
39 	return cbfs_map(name, NULL);
40 }
41 
pci_rom_probe(const struct device * dev)42 struct rom_header *pci_rom_probe(const struct device *dev)
43 {
44 	struct rom_header *rom_header = NULL;
45 	struct pci_data *rom_data;
46 	u32 vendev = (dev->vendor << 16) | dev->device;
47 	u32 mapped_vendev = vendev;
48 
49 	/* If the ROM is in flash, then don't check the PCI device for it. */
50 	mapped_vendev = map_oprom_vendev(vendev);
51 	rom_header = cbfs_boot_map_optionrom(mapped_vendev >> 16, mapped_vendev & 0xffff);
52 
53 	/* Handle the case of VGA_BIOS_ID not being set to the remapped PCI ID. This is a
54 	   workaround that should be removed once the underlying issue is fixed. */
55 	if (!rom_header && vendev != mapped_vendev) {
56 		rom_header = cbfs_boot_map_optionrom(vendev >> 16, vendev & 0xffff);
57 		if (rom_header) {
58 			printk(BIOS_NOTICE, "VGA_BIOS_ID should be the remapped PCI ID "
59 					    "%04hx,%04hx in the VBIOS file\n",
60 			       mapped_vendev >> 16, mapped_vendev & 0xffff);
61 		}
62 	}
63 
64 	if (rom_header) {
65 		printk(BIOS_DEBUG, "In CBFS, ROM address for %s = %p\n",
66 		       dev_path(dev), rom_header);
67 	} else if (CONFIG(ON_DEVICE_ROM_LOAD)) {
68 		uintptr_t rom_address;
69 
70 		rom_address = pci_read_config32(dev, PCI_ROM_ADDRESS);
71 
72 		if (rom_address == 0x00000000 || rom_address == 0xffffffff) {
73 			if (CONFIG(CPU_QEMU_X86) && (dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
74 				rom_address = 0xc0000;
75 			else
76 				return NULL;
77 		} else {
78 			/* Enable expansion ROM address decoding. */
79 			pci_write_config32(dev, PCI_ROM_ADDRESS,
80 					   rom_address|PCI_ROM_ADDRESS_ENABLE);
81 		}
82 
83 		rom_address &= PCI_ROM_ADDRESS_MASK;
84 
85 		printk(BIOS_DEBUG, "Option ROM address for %s = %lx\n",
86 		       dev_path(dev), (unsigned long)rom_address);
87 		rom_header = (struct rom_header *)rom_address;
88 	} else {
89 		printk(BIOS_DEBUG, "PCI Option ROM loading disabled for %s\n",
90 		       dev_path(dev));
91 		return NULL;
92 	}
93 
94 	printk(BIOS_SPEW,
95 	       "PCI expansion ROM, signature 0x%04x, INIT size 0x%04x, data ptr 0x%04x\n",
96 	       le32_to_cpu(rom_header->signature),
97 	       rom_header->size * 512, le32_to_cpu(rom_header->data));
98 
99 	if (le32_to_cpu(rom_header->signature) != PCI_ROM_HDR) {
100 		printk(BIOS_ERR, "Incorrect expansion ROM header signature %04x\n",
101 		       le32_to_cpu(rom_header->signature));
102 		return NULL;
103 	}
104 
105 	rom_data = (((void *)rom_header) + le32_to_cpu(rom_header->data));
106 
107 	printk(BIOS_SPEW, "PCI ROM image, vendor ID %04x, device ID %04x,\n",
108 	       rom_data->vendor, rom_data->device);
109 	/* If the device id is mapped, a mismatch is expected */
110 	if ((dev->vendor != rom_data->vendor
111 	    || dev->device != rom_data->device)
112 	    && (vendev == mapped_vendev)) {
113 		printk(BIOS_ERR, "ID mismatch: vendor ID %04x, device ID %04x\n",
114 		       dev->vendor, dev->device);
115 		return NULL;
116 	}
117 
118 	printk(BIOS_SPEW, "PCI ROM image, Class Code %04x%02x, Code Type %02x\n",
119 	       rom_data->class_hi, rom_data->class_lo,
120 	       rom_data->type);
121 
122 	if (dev->class != ((rom_data->class_hi << 8) | rom_data->class_lo)) {
123 		printk(BIOS_DEBUG, "Class Code mismatch ROM %08x, dev %08x\n",
124 		       (rom_data->class_hi << 8) | rom_data->class_lo,
125 		       dev->class);
126 		// return NULL;
127 	}
128 
129 	return rom_header;
130 }
131 
132 static void *pci_ram_image_start = (void *)PCI_RAM_IMAGE_START;
133 
pci_rom_load(struct device * dev,struct rom_header * rom_header)134 struct rom_header *pci_rom_load(struct device *dev,
135 				struct rom_header *rom_header)
136 {
137 	struct pci_data * rom_data;
138 	unsigned int rom_size;
139 	unsigned int image_size=0;
140 
141 	do {
142 		/* Get next image. */
143 		rom_header = (struct rom_header *)((void *)rom_header
144 							    + image_size);
145 
146 		rom_data = (struct pci_data *)((void *)rom_header
147 				+ le32_to_cpu(rom_header->data));
148 
149 		image_size = le32_to_cpu(rom_data->ilen) * 512;
150 	} while ((rom_data->type != 0) && (rom_data->indicator != 0)); // make sure we got x86 version
151 
152 	if (rom_data->type != 0)
153 		return NULL;
154 
155 	rom_size = rom_header->size * 512;
156 
157 	/*
158 	 * We check to see if the device thinks it is a VGA device not
159 	 * whether the ROM image is for a VGA device because some
160 	 * devices have a mismatch between the hardware and the ROM.
161 	 */
162 	if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
163 		extern struct device *vga_pri; /* Primary VGA device (device.c). */
164 		if (dev != vga_pri) return NULL; /* Only one VGA supported. */
165 		if ((void *)PCI_VGA_RAM_IMAGE_START != rom_header) {
166 			printk(BIOS_DEBUG,
167 			       "Copying VGA ROM Image from %p to 0x%x, 0x%x bytes\n",
168 			       rom_header, PCI_VGA_RAM_IMAGE_START, rom_size);
169 			memcpy((void *)PCI_VGA_RAM_IMAGE_START, rom_header,
170 			       rom_size);
171 		}
172 		return (struct rom_header *)(PCI_VGA_RAM_IMAGE_START);
173 	}
174 
175 	printk(BIOS_DEBUG, "Copying non-VGA ROM image from %p to %p, 0x%x bytes\n",
176 	       rom_header, pci_ram_image_start, rom_size);
177 
178 	memcpy(pci_ram_image_start, rom_header, rom_size);
179 	pci_ram_image_start += rom_size;
180 	return (struct rom_header *)(pci_ram_image_start-rom_size);
181 }
182 
183 /* ACPI */
184 #if CONFIG(HAVE_ACPI_TABLES)
185 
186 /* VBIOS may be modified after oprom init so use the copy if present. */
check_initialized(const struct device * dev)187 static struct rom_header *check_initialized(const struct device *dev)
188 {
189 	struct rom_header *run_rom;
190 	struct pci_data *rom_data;
191 
192 	if (!CONFIG(VGA_ROM_RUN) && !CONFIG(RUN_FSP_GOP))
193 		return NULL;
194 
195 	run_rom = (struct rom_header *)(uintptr_t)PCI_VGA_RAM_IMAGE_START;
196 	if (read_le16(&run_rom->signature) != PCI_ROM_HDR)
197 		return NULL;
198 
199 	rom_data = (struct pci_data *)((u8 *)run_rom
200 			+ read_le16(&run_rom->data));
201 
202 	if (read_le32(&rom_data->signature) == PCI_DATA_HDR
203 			&& read_le16(&rom_data->device) == dev->device
204 			&& read_le16(&rom_data->vendor) == dev->vendor)
205 		return run_rom;
206 	else
207 		return NULL;
208 }
209 
210 static unsigned long
ati_rom_acpi_fill_vfct(const struct device * device,acpi_vfct_t * vfct_struct,unsigned long current)211 ati_rom_acpi_fill_vfct(const struct device *device, acpi_vfct_t *vfct_struct,
212 		       unsigned long current)
213 {
214 	acpi_vfct_image_hdr_t *header = &vfct_struct->image_hdr;
215 	struct rom_header *rom;
216 
217 	rom = check_initialized(device);
218 	if (!rom)
219 		rom = pci_rom_probe(device);
220 	if (!rom) {
221 		printk(BIOS_ERR, "%s failed\n", __func__);
222 		return current;
223 	}
224 	if (device->upstream->segment_group) {
225 		printk(BIOS_ERR, "VFCT only supports GPU in first PCI segment group.\n");
226 		return current;
227 	}
228 
229 	printk(BIOS_DEBUG, "           Copying %sVBIOS image from %p\n",
230 			rom == (struct rom_header *)
231 					(uintptr_t)PCI_VGA_RAM_IMAGE_START ?
232 			"initialized " : "",
233 			rom);
234 
235 	header->DeviceID = device->device;
236 	header->VendorID = device->vendor;
237 	header->PCIBus = device->upstream->secondary;
238 	header->PCIFunction = PCI_FUNC(device->path.pci.devfn);
239 	header->PCIDevice = PCI_SLOT(device->path.pci.devfn);
240 	header->ImageLength = rom->size * 512;
241 	memcpy((void *)header->VbiosContent, rom, header->ImageLength);
242 
243 	vfct_struct->VBIOSImageOffset = (size_t)header - (size_t)vfct_struct;
244 
245 	/* Calculate and set checksum for VBIOS data if FSP GOP driver used,
246 	   Since GOP driver modifies ATOMBIOS tables at end of VBIOS */
247 	if (CONFIG(RUN_FSP_GOP)) {
248 		/* Clear existing checksum before recalculating */
249 		header->VbiosContent[VFCT_VBIOS_CHECKSUM_OFFSET] = 0;
250 		header->VbiosContent[VFCT_VBIOS_CHECKSUM_OFFSET] =
251 				acpi_checksum(header->VbiosContent, header->ImageLength);
252 	}
253 
254 	current += header->ImageLength;
255 	return current;
256 }
257 
258 unsigned long
pci_rom_write_acpi_tables(const struct device * device,unsigned long current,struct acpi_rsdp * rsdp)259 pci_rom_write_acpi_tables(const struct device *device, unsigned long current,
260 			  struct acpi_rsdp *rsdp)
261 {
262 	/* Only handle VGA devices */
263 	if ((device->class >> 8) != PCI_CLASS_DISPLAY_VGA)
264 		return current;
265 
266 	/* Only handle enabled devices */
267 	if (!device->enabled)
268 		return current;
269 
270 	/* AMD/ATI uses VFCT */
271 	if (device->vendor == PCI_VID_ATI) {
272 		acpi_vfct_t *vfct;
273 
274 		current = ALIGN_UP(current, 8);
275 		vfct = (acpi_vfct_t *)current;
276 		acpi_create_vfct(device, vfct, ati_rom_acpi_fill_vfct);
277 		if (vfct->header.length) {
278 			printk(BIOS_DEBUG, "ACPI:    * VFCT at %lx\n", current);
279 			current += vfct->header.length;
280 			acpi_add_table(rsdp, vfct);
281 		}
282 	}
283 
284 	return current;
285 }
286 
pci_rom_ssdt(const struct device * device)287 void pci_rom_ssdt(const struct device *device)
288 {
289 	static size_t ngfx;
290 
291 	/* Only handle display devices */
292 	if ((device->class >> 16) != PCI_BASE_CLASS_DISPLAY)
293 		return;
294 
295 	/* Only handle enabled devices */
296 	if (!device->enabled)
297 		return;
298 
299 	/* Probe for option rom */
300 	const struct rom_header *rom = pci_rom_probe(device);
301 	if (!rom || !rom->size) {
302 		printk(BIOS_WARNING, "%s: Missing PCI Option ROM\n",
303 		       dev_path(device));
304 		return;
305 	}
306 
307 	const char *scope = acpi_device_path(device);
308 	if (!scope) {
309 		printk(BIOS_ERR, "%s: Missing ACPI scope\n", dev_path(device));
310 		return;
311 	}
312 
313 	/* Supports up to four devices. */
314 	if ((CBMEM_ID_ROM0 + ngfx) > CBMEM_ID_ROM3) {
315 		printk(BIOS_ERR, "%s: Out of CBMEM IDs.\n", dev_path(device));
316 		return;
317 	}
318 
319 	/* Prepare memory */
320 	const size_t cbrom_length = rom->size * 512;
321 	if (!cbrom_length) {
322 		printk(BIOS_ERR, "%s: ROM has zero length!\n",
323 		       dev_path(device));
324 		return;
325 	}
326 
327 	void *cbrom = cbmem_add(CBMEM_ID_ROM0 + ngfx, cbrom_length);
328 	if (!cbrom) {
329 		printk(BIOS_ERR, "%s: Failed to allocate CBMEM.\n",
330 		       dev_path(device));
331 		return;
332 	}
333 	/* Increment CBMEM id for next device */
334 	ngfx++;
335 
336 	memcpy(cbrom, rom, cbrom_length);
337 
338 	/* write _ROM method */
339 	acpigen_write_scope(scope);
340 	acpigen_write_rom(cbrom, cbrom_length);
341 	acpigen_pop_len(); /* pop scope */
342 }
343 #endif
344