1 // Option rom scanning code.
2 //
3 // Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2002 MandrakeSoft S.A.
5 //
6 // This file may be distributed under the terms of the GNU LGPLv3 license.
7
8 #include "bregs.h" // struct bregs
9 #include "config.h" // CONFIG_*
10 #include "farptr.h" // FLATPTR_TO_SEG
11 #include "biosvar.h" // GET_IVT
12 #include "hw/pci.h" // pci_config_readl
13 #include "hw/pcidevice.h" // foreachpci
14 #include "hw/pci_ids.h" // PCI_CLASS_DISPLAY_VGA
15 #include "hw/pci_regs.h" // PCI_ROM_ADDRESS
16 #include "malloc.h" // rom_confirm
17 #include "output.h" // dprintf
18 #include "romfile.h" // romfile_loadint
19 #include "stacks.h" // farcall16big
20 #include "std/optionrom.h" // struct rom_header
21 #include "std/pnpbios.h" // PNP_SIGNATURE
22 #include "string.h" // memset
23 #include "util.h" // get_pnp_offset
24 #include "tcgbios.h" // tpm_*
25
26 static int EnforceChecksum, S3ResumeVga, RunPCIroms;
27
28
29 /****************************************************************
30 * Helper functions
31 ****************************************************************/
32
33 // Execute a given option rom.
34 static void
__callrom(struct rom_header * rom,u16 offset,u16 bdf)35 __callrom(struct rom_header *rom, u16 offset, u16 bdf)
36 {
37 u16 seg = FLATPTR_TO_SEG(rom);
38 dprintf(1, "Running option rom at %04x:%04x\n", seg, offset);
39
40 struct bregs br;
41 memset(&br, 0, sizeof(br));
42 br.flags = F_IF;
43 br.ax = bdf;
44 br.bx = 0xffff;
45 br.dx = 0xffff;
46 br.es = SEG_BIOS;
47 br.di = get_pnp_offset();
48 br.code = SEGOFF(seg, offset);
49 start_preempt();
50 farcall16big(&br);
51 finish_preempt();
52 }
53
54 // Execute a given option rom at the standard entry vector.
55 void
callrom(struct rom_header * rom,u16 bdf)56 callrom(struct rom_header *rom, u16 bdf)
57 {
58 __callrom(rom, OPTION_ROM_INITVECTOR, bdf);
59 }
60
61 // Execute a BCV option rom registered via add_bcv().
62 void
call_bcv(u16 seg,u16 ip)63 call_bcv(u16 seg, u16 ip)
64 {
65 __callrom(MAKE_FLATPTR(seg, 0), ip, 0);
66 }
67
68 // Verify that an option rom looks valid
69 static int
is_valid_rom(struct rom_header * rom)70 is_valid_rom(struct rom_header *rom)
71 {
72 dprintf(6, "Checking rom %p (sig %x size %d)\n"
73 , rom, rom->signature, rom->size);
74 if (rom->signature != OPTION_ROM_SIGNATURE)
75 return 0;
76 if (! rom->size)
77 return 0;
78 u32 len = rom->size * 512;
79 u8 sum = checksum(rom, len);
80 if (sum != 0) {
81 dprintf(1, "Found option rom with bad checksum: loc=%p len=%d sum=%x\n"
82 , rom, len, sum);
83 if (EnforceChecksum)
84 return 0;
85 }
86 return 1;
87 }
88
89 // Check if a valid option rom has a pnp struct; return it if so.
90 static struct pnp_data *
get_pnp_rom(struct rom_header * rom)91 get_pnp_rom(struct rom_header *rom)
92 {
93 struct pnp_data *pnp = (void*)((u8*)rom + rom->pnpoffset);
94 if (pnp->signature != PNP_SIGNATURE)
95 return NULL;
96 return pnp;
97 }
98
99 // Check for multiple pnp option rom headers.
100 static struct pnp_data *
get_pnp_next(struct rom_header * rom,struct pnp_data * pnp)101 get_pnp_next(struct rom_header *rom, struct pnp_data *pnp)
102 {
103 if (! pnp->nextoffset)
104 return NULL;
105 pnp = (void*)((u8*)rom + pnp->nextoffset);
106 if (pnp->signature != PNP_SIGNATURE)
107 return NULL;
108 return pnp;
109 }
110
111 // Check if a valid option rom has a pci struct; return it if so.
112 static struct pci_data *
get_pci_rom(struct rom_header * rom)113 get_pci_rom(struct rom_header *rom)
114 {
115 struct pci_data *pd = (void*)((u32)rom + rom->pcioffset);
116 if (pd->signature != PCI_ROM_SIGNATURE)
117 return NULL;
118 if (rom->pcioffset & 3)
119 dprintf(1, "WARNING! Found unaligned PCI rom (vd=%04x:%04x)\n"
120 , pd->vendor, pd->device);
121 return pd;
122 }
123
124 // Run rom init code and note rom size.
125 static int
init_optionrom(struct rom_header * rom,u16 bdf,int isvga)126 init_optionrom(struct rom_header *rom, u16 bdf, int isvga)
127 {
128 if (! is_valid_rom(rom))
129 return -1;
130 struct rom_header *newrom = rom_reserve(rom->size * 512);
131 if (!newrom) {
132 warn_noalloc();
133 return -1;
134 }
135 if (newrom != rom)
136 memmove(newrom, rom, rom->size * 512);
137
138 tpm_option_rom(newrom, rom->size * 512);
139
140 if (isvga || get_pnp_rom(newrom))
141 // Only init vga and PnP roms here.
142 callrom(newrom, bdf);
143
144 return rom_confirm(newrom->size * 512);
145 }
146
147 #define RS_PCIROM (1LL<<33)
148
149 static void
setRomSource(u64 * sources,struct rom_header * rom,u64 source)150 setRomSource(u64 *sources, struct rom_header *rom, u64 source)
151 {
152 if (sources)
153 sources[((u32)rom - BUILD_ROM_START) / OPTION_ROM_ALIGN] = source;
154 }
155
156 static int
getRomPriority(u64 * sources,struct rom_header * rom,int instance)157 getRomPriority(u64 *sources, struct rom_header *rom, int instance)
158 {
159 u64 source = sources[((u32)rom - BUILD_ROM_START) / OPTION_ROM_ALIGN];
160 if (!source)
161 return -1;
162 if (source & RS_PCIROM)
163 return bootprio_find_pci_rom((void*)(u32)source, instance);
164 struct romfile_s *file = (void*)(u32)source;
165 return bootprio_find_named_rom(file->name, instance);
166 }
167
168
169 /****************************************************************
170 * Roms in CBFS
171 ****************************************************************/
172
173 static struct rom_header *
deploy_romfile(struct romfile_s * file)174 deploy_romfile(struct romfile_s *file)
175 {
176 u32 size = file->size;
177 struct rom_header *rom = rom_reserve(size);
178 if (!rom) {
179 warn_noalloc();
180 return NULL;
181 }
182 int ret = file->copy(file, rom, size);
183 if (ret <= 0)
184 return NULL;
185 return rom;
186 }
187
188 // Run all roms in a given CBFS directory.
189 static void
run_file_roms(const char * prefix,int isvga,u64 * sources)190 run_file_roms(const char *prefix, int isvga, u64 *sources)
191 {
192 struct romfile_s *file = NULL;
193 for (;;) {
194 file = romfile_findprefix(prefix, file);
195 if (!file)
196 break;
197 struct rom_header *rom = deploy_romfile(file);
198 if (rom) {
199 setRomSource(sources, rom, (u32)file);
200 init_optionrom(rom, 0, isvga);
201 }
202 }
203 }
204
205
206 /****************************************************************
207 * PCI roms
208 ****************************************************************/
209
210 // Verify device is a vga device with legacy address decoding enabled.
211 int
is_pci_vga(struct pci_device * pci)212 is_pci_vga(struct pci_device *pci)
213 {
214 if (pci->class != PCI_CLASS_DISPLAY_VGA)
215 return 0;
216 u16 cmd = pci_config_readw(pci->bdf, PCI_COMMAND);
217 if (!(cmd & PCI_COMMAND_IO && cmd & PCI_COMMAND_MEMORY))
218 return 0;
219 while (pci->parent) {
220 pci = pci->parent;
221 u32 ctrl = pci_config_readb(pci->bdf, PCI_BRIDGE_CONTROL);
222 if (!(ctrl & PCI_BRIDGE_CTL_VGA))
223 return 0;
224 }
225 return 1;
226 }
227
228 // Copy a rom to its permanent location below 1MiB
229 static struct rom_header *
copy_rom(struct rom_header * rom)230 copy_rom(struct rom_header *rom)
231 {
232 u32 romsize = rom->size * 512;
233 struct rom_header *newrom = rom_reserve(romsize);
234 if (!newrom) {
235 warn_noalloc();
236 return NULL;
237 }
238 dprintf(4, "Copying option rom (size %d) from %p to %p\n"
239 , romsize, rom, newrom);
240 iomemcpy(newrom, rom, romsize);
241 return newrom;
242 }
243
244 // Map the option rom of a given PCI device.
245 static struct rom_header *
map_pcirom(struct pci_device * pci)246 map_pcirom(struct pci_device *pci)
247 {
248 dprintf(6, "Attempting to map option rom on dev %pP\n", pci);
249
250 if ((pci->header_type & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
251 dprintf(6, "Skipping non-normal pci device (type=%x)\n"
252 , pci->header_type);
253 return NULL;
254 }
255
256 u16 bdf = pci->bdf;
257 u32 orig = pci_config_readl(bdf, PCI_ROM_ADDRESS);
258 pci_config_writel(bdf, PCI_ROM_ADDRESS, ~PCI_ROM_ADDRESS_ENABLE);
259 u32 sz = pci_config_readl(bdf, PCI_ROM_ADDRESS);
260
261 dprintf(6, "Option rom sizing returned %x %x\n", orig, sz);
262 orig &= ~PCI_ROM_ADDRESS_ENABLE;
263 if (!sz || sz == 0xffffffff)
264 goto fail;
265
266 if (orig == sz || (u32)(orig + 4*1024*1024) < 20*1024*1024) {
267 // Don't try to map to a pci addresses at its max, in the last
268 // 4MiB of ram, or the first 16MiB of ram.
269 dprintf(6, "Preset rom address doesn't look valid\n");
270 goto fail;
271 }
272
273 // Looks like a rom - enable it.
274 pci_config_writel(bdf, PCI_ROM_ADDRESS, orig | PCI_ROM_ADDRESS_ENABLE);
275
276 struct rom_header *rom = (void*)orig;
277 for (;;) {
278 dprintf(5, "Inspecting possible rom at %p (vd=%04x:%04x bdf=%pP)\n"
279 , rom, pci->vendor, pci->device, pci);
280 if (rom->signature != OPTION_ROM_SIGNATURE) {
281 dprintf(6, "No option rom signature (got %x)\n", rom->signature);
282 goto fail;
283 }
284 struct pci_data *pd = get_pci_rom(rom);
285 if (! pd) {
286 dprintf(6, "No valid pci signature found\n");
287 goto fail;
288 }
289
290 if (pd->vendor == pci->vendor && pd->device == pci->device
291 && pd->type == PCIROM_CODETYPE_X86)
292 // A match
293 break;
294 dprintf(6, "Didn't match dev/ven (got %04x:%04x) or type (got %d)\n"
295 , pd->vendor, pd->device, pd->type);
296 if (pd->indicator & 0x80) {
297 dprintf(6, "No more images left\n");
298 goto fail;
299 }
300 rom = (void*)((u32)rom + pd->ilen * 512);
301 }
302
303 rom = copy_rom(rom);
304 pci_config_writel(bdf, PCI_ROM_ADDRESS, orig);
305 return rom;
306 fail:
307 // Not valid - restore original and exit.
308 pci_config_writel(bdf, PCI_ROM_ADDRESS, orig);
309 return NULL;
310 }
311
boot_irq_captured(void)312 static int boot_irq_captured(void)
313 {
314 return GET_IVT(0x19).segoff != FUNC16(entry_19_official).segoff;
315 }
316
boot_irq_restore(void)317 static void boot_irq_restore(void)
318 {
319 struct segoff_s seabios;
320
321 seabios = FUNC16(entry_19_official);
322 SET_IVT(0x19, seabios);
323 }
324
325 // Attempt to map and initialize the option rom on a given PCI device.
326 static void
init_pcirom(struct pci_device * pci,int isvga,u64 * sources)327 init_pcirom(struct pci_device *pci, int isvga, u64 *sources)
328 {
329 dprintf(4, "Attempting to init PCI bdf %pP (vd %04x:%04x)\n"
330 , pci, pci->vendor, pci->device);
331
332 char fname[17];
333 snprintf(fname, sizeof(fname), "pci%04x,%04x.rom"
334 , pci->vendor, pci->device);
335 struct romfile_s *file = romfile_find(fname);
336 struct rom_header *rom = NULL;
337 if (file)
338 rom = deploy_romfile(file);
339 else if (RunPCIroms > 1 || (RunPCIroms == 1 && isvga))
340 rom = map_pcirom(pci);
341 if (! rom)
342 // No ROM present.
343 return;
344 int irq_was_captured = boot_irq_captured();
345 struct pnp_data *pnp = get_pnp_rom(rom);
346 setRomSource(sources, rom, RS_PCIROM | (u32)pci);
347 init_optionrom(rom, pci->bdf, isvga);
348 if (boot_irq_captured() && !irq_was_captured &&
349 !file && !isvga && pnp) {
350 // This PCI rom is misbehaving - recapture the boot irqs
351 char *desc = MAKE_FLATPTR(FLATPTR_TO_SEG(rom), pnp->productname);
352 dprintf(1, "PnP optionrom \"%s\" (bdf %pP) captured int19, restoring\n",
353 desc, pci);
354 boot_irq_restore();
355 }
356 }
357
358
359 /****************************************************************
360 * Non-VGA option rom init
361 ****************************************************************/
362
363 void
optionrom_setup(void)364 optionrom_setup(void)
365 {
366 if (! CONFIG_OPTIONROMS)
367 return;
368
369 dprintf(1, "Scan for option roms\n");
370 u64 sources[(BUILD_BIOS_ADDR - BUILD_ROM_START) / OPTION_ROM_ALIGN];
371 memset(sources, 0, sizeof(sources));
372 u32 post_vga = rom_get_last();
373
374 // Find and deploy PCI roms.
375 struct pci_device *pci;
376 foreachpci(pci) {
377 if (pci->class == PCI_CLASS_DISPLAY_VGA ||
378 pci->class == PCI_CLASS_DISPLAY_OTHER ||
379 pci->have_driver)
380 continue;
381 init_pcirom(pci, 0, sources);
382 }
383
384 // Find and deploy CBFS roms not associated with a device.
385 run_file_roms("genroms/", 0, sources);
386 rom_reserve(0);
387
388 // All option roms found and deployed - now build BEV/BCV vectors.
389
390 u32 pos = post_vga;
391 while (pos < rom_get_last()) {
392 struct rom_header *rom = (void*)pos;
393 if (! is_valid_rom(rom)) {
394 pos += OPTION_ROM_ALIGN;
395 continue;
396 }
397 pos += ALIGN(rom->size * 512, OPTION_ROM_ALIGN);
398 struct pnp_data *pnp = get_pnp_rom(rom);
399 if (! pnp) {
400 // Legacy rom.
401 boot_add_bcv(FLATPTR_TO_SEG(rom), OPTION_ROM_INITVECTOR, 0
402 , getRomPriority(sources, rom, 0));
403 continue;
404 }
405 // PnP rom - check for BEV and BCV boot capabilities.
406 int instance = 0;
407 while (pnp) {
408 if (pnp->bev)
409 boot_add_bev(FLATPTR_TO_SEG(rom), pnp->bev, pnp->productname
410 , getRomPriority(sources, rom, instance++));
411 else if (pnp->bcv)
412 boot_add_bcv(FLATPTR_TO_SEG(rom), pnp->bcv, pnp->productname
413 , getRomPriority(sources, rom, instance++));
414 else
415 break;
416 pnp = get_pnp_next(rom, pnp);
417 }
418 }
419 }
420
421
422 /****************************************************************
423 * VGA init
424 ****************************************************************/
425
426 int ScreenAndDebug;
427 struct rom_header *VgaROM;
428
try_setup_display_other(void)429 static void try_setup_display_other(void)
430 {
431 struct pci_device *pci;
432
433 dprintf(1, "No VGA found, scan for other display\n");
434
435 foreachpci(pci) {
436 if (pci->class != PCI_CLASS_DISPLAY_OTHER)
437 continue;
438 struct rom_header *rom = map_pcirom(pci);
439 if (!rom)
440 continue;
441 dprintf(1, "Other display found at %pP\n", pci);
442 pci_config_maskw(pci->bdf, PCI_COMMAND, 0,
443 PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
444 init_optionrom(rom, pci->bdf, 1);
445 return;
446 }
447 }
448
449 // Call into vga code to turn on console.
450 void
vgarom_setup(void)451 vgarom_setup(void)
452 {
453 int have_vga = 0;
454
455 if (! CONFIG_OPTIONROMS)
456 return;
457
458 dprintf(1, "Scan for VGA option rom\n");
459
460 // Load some config settings that impact VGA.
461 EnforceChecksum = romfile_loadint("etc/optionroms-checksum", 1);
462 S3ResumeVga = romfile_loadint("etc/s3-resume-vga-init", CONFIG_QEMU);
463 RunPCIroms = romfile_loadint("etc/pci-optionrom-exec", 2);
464 ScreenAndDebug = romfile_loadint("etc/screen-and-debug", 1);
465
466 // Clear option rom memory
467 memset((void*)BUILD_ROM_START, 0, rom_get_max() - BUILD_ROM_START);
468
469 // Find and deploy PCI VGA rom.
470 struct pci_device *pci;
471 foreachpci(pci) {
472 if (!is_pci_vga(pci))
473 continue;
474 vgahook_setup(pci);
475 init_pcirom(pci, 1, NULL);
476 have_vga = 1;
477 break;
478 }
479 if (!have_vga)
480 try_setup_display_other();
481
482 // Find and deploy CBFS vga-style roms not associated with a device.
483 run_file_roms("vgaroms/", 1, NULL);
484 rom_reserve(0);
485
486 if (rom_get_last() != BUILD_ROM_START)
487 // VGA rom found
488 VgaROM = (void*)BUILD_ROM_START;
489 }
490
491 void
s3_resume_vga(void)492 s3_resume_vga(void)
493 {
494 if (!S3ResumeVga)
495 return;
496 if (!VgaROM || ! is_valid_rom(VgaROM))
497 return;
498 callrom(VgaROM, 0);
499 }
500