Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


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