~ubuntu-branches/ubuntu/oneiric/seabios/oneiric

« back to all changes in this revision

Viewing changes to .pc/debian-changes-0.6.0-0ubuntu2/src/optionroms.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2010-10-22 11:04:31 UTC
  • Revision ID: james.westby@ubuntu.com-20101022110431-fnfj73ra6xkq623n
Tags: 0.6.0-0ubuntu2
Add all patches which were included in qemu-0.13.0-rc2 (per
commit on Jul 13, 2010).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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;
 
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
// Verify that an option rom looks valid
 
120
static int
 
121
is_valid_rom(struct rom_header *rom)
 
122
{
 
123
    dprintf(6, "Checking rom %p (sig %x size %d)\n"
 
124
            , rom, rom->signature, rom->size);
 
125
    if (rom->signature != OPTION_ROM_SIGNATURE)
 
126
        return 0;
 
127
    if (! rom->size)
 
128
        return 0;
 
129
    u32 len = rom->size * 512;
 
130
    u8 sum = checksum(rom, len);
 
131
    if (sum != 0) {
 
132
        dprintf(1, "Found option rom with bad checksum: loc=%p len=%d sum=%x\n"
 
133
                , rom, len, sum);
 
134
        return 0;
 
135
    }
 
136
    return 1;
 
137
}
 
138
 
 
139
// Check if a valid option rom has a pnp struct; return it if so.
 
140
static struct pnp_data *
 
141
get_pnp_rom(struct rom_header *rom)
 
142
{
 
143
    struct pnp_data *pnp = (void*)((u8*)rom + rom->pnpoffset);
 
144
    if (pnp->signature != PNP_SIGNATURE)
 
145
        return NULL;
 
146
    return pnp;
 
147
}
 
148
 
 
149
// Check for multiple pnp option rom headers.
 
150
static struct pnp_data *
 
151
get_pnp_next(struct rom_header *rom, struct pnp_data *pnp)
 
152
{
 
153
    if (! pnp->nextoffset)
 
154
        return NULL;
 
155
    pnp = (void*)((u8*)rom + pnp->nextoffset);
 
156
    if (pnp->signature != PNP_SIGNATURE)
 
157
        return NULL;
 
158
    return pnp;
 
159
}
 
160
 
 
161
// Check if a valid option rom has a pci struct; return it if so.
 
162
static struct pci_data *
 
163
get_pci_rom(struct rom_header *rom)
 
164
{
 
165
    struct pci_data *pci = (void*)((u32)rom + rom->pcioffset);
 
166
    if (pci->signature != PCI_ROM_SIGNATURE)
 
167
        return NULL;
 
168
    return pci;
 
169
}
 
170
 
 
171
// Return the memory position up to which roms may be located.
 
172
static inline u32
 
173
max_rom(void)
 
174
{
 
175
    extern u8 code32flat_start[];
 
176
    if ((u32)code32flat_start > BUILD_BIOS_ADDR)
 
177
        return BUILD_BIOS_ADDR;
 
178
    return (u32)code32flat_start;
 
179
}
 
180
 
 
181
// Copy a rom to its permanent location below 1MiB
 
182
static struct rom_header *
 
183
copy_rom(struct rom_header *rom)
 
184
{
 
185
    u32 romsize = rom->size * 512;
 
186
    if (RomEnd + romsize > max_rom()) {
 
187
        // Option rom doesn't fit.
 
188
        warn_noalloc();
 
189
        return NULL;
 
190
    }
 
191
    dprintf(4, "Copying option rom (size %d) from %p to %x\n"
 
192
            , romsize, rom, RomEnd);
 
193
    iomemcpy((void*)RomEnd, rom, romsize);
 
194
    return (void*)RomEnd;
 
195
}
 
196
 
 
197
// Run rom init code and note rom size.
 
198
static int
 
199
init_optionrom(struct rom_header *rom, u16 bdf, int isvga)
 
200
{
 
201
    if (! is_valid_rom(rom))
 
202
        return -1;
 
203
 
 
204
    if (isvga || get_pnp_rom(rom))
 
205
        // Only init vga and PnP roms here.
 
206
        callrom(rom, bdf);
 
207
 
 
208
    RomEnd = (u32)rom + ALIGN(rom->size * 512, OPTION_ROM_ALIGN);
 
209
 
 
210
    return 0;
 
211
}
 
212
 
 
213
 
 
214
/****************************************************************
 
215
 * Roms in CBFS
 
216
 ****************************************************************/
 
217
 
 
218
// Check if an option rom is at a hardcoded location or in CBFS.
 
219
static struct rom_header *
 
220
lookup_hardcode(u32 vendev)
 
221
{
 
222
    if (OPTIONROM_VENDEV_1
 
223
        && ((OPTIONROM_VENDEV_1 >> 16)
 
224
            | ((OPTIONROM_VENDEV_1 & 0xffff)) << 16) == vendev)
 
225
        return copy_rom((void*)OPTIONROM_MEM_1);
 
226
    if (OPTIONROM_VENDEV_2
 
227
        && ((OPTIONROM_VENDEV_2 >> 16)
 
228
            | ((OPTIONROM_VENDEV_2 & 0xffff)) << 16) == vendev)
 
229
        return copy_rom((void*)OPTIONROM_MEM_2);
 
230
    char fname[17];
 
231
    snprintf(fname, sizeof(fname), "pci%04x,%04x.rom"
 
232
             , pci_vd_to_ven(vendev), pci_vd_to_dev(vendev));
 
233
    int ret = romfile_copy(romfile_find(fname), (void*)RomEnd
 
234
                           , max_rom() - RomEnd);
 
235
    if (ret <= 0)
 
236
        return NULL;
 
237
    return (void*)RomEnd;
 
238
}
 
239
 
 
240
// Run all roms in a given CBFS directory.
 
241
static void
 
242
run_file_roms(const char *prefix, int isvga)
 
243
{
 
244
    u32 file = 0;
 
245
    for (;;) {
 
246
        file = romfile_findprefix(prefix, file);
 
247
        if (!file)
 
248
            break;
 
249
        int ret = romfile_copy(file, (void*)RomEnd, max_rom() - RomEnd);
 
250
        if (ret > 0)
 
251
            init_optionrom((void*)RomEnd, 0, isvga);
 
252
    }
 
253
}
 
254
 
 
255
 
 
256
/****************************************************************
 
257
 * PCI roms
 
258
 ****************************************************************/
 
259
 
 
260
// Map the option rom of a given PCI device.
 
261
static struct rom_header *
 
262
map_pcirom(u16 bdf, u32 vendev)
 
263
{
 
264
    dprintf(6, "Attempting to map option rom on dev %02x:%02x.%x\n"
 
265
            , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf));
 
266
 
 
267
    u8 htype = pci_config_readb(bdf, PCI_HEADER_TYPE);
 
268
    if ((htype & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
 
269
        dprintf(6, "Skipping non-normal pci device (type=%x)\n", htype);
 
270
        return NULL;
 
271
    }
 
272
 
 
273
    u32 orig = pci_config_readl(bdf, PCI_ROM_ADDRESS);
 
274
    pci_config_writel(bdf, PCI_ROM_ADDRESS, ~PCI_ROM_ADDRESS_ENABLE);
 
275
    u32 sz = pci_config_readl(bdf, PCI_ROM_ADDRESS);
 
276
 
 
277
    dprintf(6, "Option rom sizing returned %x %x\n", orig, sz);
 
278
    orig &= ~PCI_ROM_ADDRESS_ENABLE;
 
279
    if (!sz || sz == 0xffffffff)
 
280
        goto fail;
 
281
 
 
282
    if (orig == sz || (u32)(orig + 4*1024*1024) < 20*1024*1024) {
 
283
        // Don't try to map to a pci addresses at its max, in the last
 
284
        // 4MiB of ram, or the first 16MiB of ram.
 
285
        dprintf(6, "Preset rom address doesn't look valid\n");
 
286
        goto fail;
 
287
    }
 
288
 
 
289
    // Looks like a rom - enable it.
 
290
    pci_config_writel(bdf, PCI_ROM_ADDRESS, orig | PCI_ROM_ADDRESS_ENABLE);
 
291
 
 
292
    struct rom_header *rom = (void*)orig;
 
293
    for (;;) {
 
294
        dprintf(5, "Inspecting possible rom at %p (vd=%04x:%04x"
 
295
                " bdf=%02x:%02x.%x)\n"
 
296
                , rom, pci_vd_to_ven(vendev), pci_vd_to_dev(vendev)
 
297
                , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf));
 
298
        if (rom->signature != OPTION_ROM_SIGNATURE) {
 
299
            dprintf(6, "No option rom signature (got %x)\n", rom->signature);
 
300
            goto fail;
 
301
        }
 
302
        struct pci_data *pci = get_pci_rom(rom);
 
303
        if (! pci) {
 
304
            dprintf(6, "No valid pci signature found\n");
 
305
            goto fail;
 
306
        }
 
307
 
 
308
        u32 vd = pci_vd(pci->vendor, pci->device);
 
309
        if (vd == vendev && pci->type == PCIROM_CODETYPE_X86)
 
310
            // A match
 
311
            break;
 
312
        dprintf(6, "Didn't match dev/ven (got %08x) or type (got %d)\n"
 
313
                , vd, pci->type);
 
314
        if (pci->indicator & 0x80) {
 
315
            dprintf(6, "No more images left\n");
 
316
            goto fail;
 
317
        }
 
318
        rom = (void*)((u32)rom + pci->ilen * 512);
 
319
    }
 
320
 
 
321
    rom = copy_rom(rom);
 
322
    pci_config_writel(bdf, PCI_ROM_ADDRESS, orig);
 
323
    return rom;
 
324
fail:
 
325
    // Not valid - restore original and exit.
 
326
    pci_config_writel(bdf, PCI_ROM_ADDRESS, orig);
 
327
    return NULL;
 
328
}
 
329
 
 
330
// Attempt to map and initialize the option rom on a given PCI device.
 
331
static int
 
332
init_pcirom(u16 bdf, int isvga)
 
333
{
 
334
    u32 vendev = pci_config_readl(bdf, PCI_VENDOR_ID);
 
335
    dprintf(4, "Attempting to init PCI bdf %02x:%02x.%x (vd %04x:%04x)\n"
 
336
            , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf)
 
337
            , pci_vd_to_ven(vendev), pci_vd_to_dev(vendev));
 
338
    struct rom_header *rom = lookup_hardcode(vendev);
 
339
    if (! rom)
 
340
        rom = map_pcirom(bdf, vendev);
 
341
    if (! rom)
 
342
        // No ROM present.
 
343
        return -1;
 
344
    return init_optionrom(rom, bdf, isvga);
 
345
}
 
346
 
 
347
 
 
348
/****************************************************************
 
349
 * Non-VGA option rom init
 
350
 ****************************************************************/
 
351
 
 
352
void
 
353
optionrom_setup(void)
 
354
{
 
355
    if (! CONFIG_OPTIONROMS)
 
356
        return;
 
357
 
 
358
    dprintf(1, "Scan for option roms\n");
 
359
 
 
360
    u32 post_vga = RomEnd;
 
361
 
 
362
    if (CONFIG_OPTIONROMS_DEPLOYED) {
 
363
        // Option roms are already deployed on the system.
 
364
        u32 pos = RomEnd;
 
365
        while (pos < max_rom()) {
 
366
            int ret = init_optionrom((void*)pos, 0, 0);
 
367
            if (ret)
 
368
                pos += OPTION_ROM_ALIGN;
 
369
            else
 
370
                pos = RomEnd;
 
371
        }
 
372
    } else {
 
373
        // Find and deploy PCI roms.
 
374
        int bdf, max;
 
375
        foreachpci(bdf, max) {
 
376
            u16 v = pci_config_readw(bdf, PCI_CLASS_DEVICE);
 
377
            if (v == 0x0000 || v == 0xffff || v == PCI_CLASS_DISPLAY_VGA
 
378
                || (CONFIG_ATA && v == PCI_CLASS_STORAGE_IDE))
 
379
                continue;
 
380
            init_pcirom(bdf, 0);
 
381
        }
 
382
 
 
383
        // Find and deploy CBFS roms not associated with a device.
 
384
        run_file_roms("genroms/", 0);
 
385
    }
 
386
 
 
387
    // All option roms found and deployed - now build BEV/BCV vectors.
 
388
 
 
389
    u32 pos = post_vga;
 
390
    while (pos < RomEnd) {
 
391
        struct rom_header *rom = (void*)pos;
 
392
        if (! is_valid_rom(rom)) {
 
393
            pos += OPTION_ROM_ALIGN;
 
394
            continue;
 
395
        }
 
396
        pos += ALIGN(rom->size * 512, OPTION_ROM_ALIGN);
 
397
        struct pnp_data *pnp = get_pnp_rom(rom);
 
398
        if (! pnp) {
 
399
            // Legacy rom.
 
400
            add_bcv(FLATPTR_TO_SEG(rom), OPTION_ROM_INITVECTOR, 0);
 
401
            continue;
 
402
        }
 
403
        // PnP rom.
 
404
        if (pnp->bev)
 
405
            // Can boot system - add to IPL list.
 
406
            add_bev(FLATPTR_TO_SEG(rom), pnp->bev, pnp->productname);
 
407
        else
 
408
            // Check for BCV (there may be multiple).
 
409
            while (pnp && pnp->bcv) {
 
410
                add_bcv(FLATPTR_TO_SEG(rom), pnp->bcv, pnp->productname);
 
411
                pnp = get_pnp_next(rom, pnp);
 
412
            }
 
413
    }
 
414
}
 
415
 
 
416
 
 
417
/****************************************************************
 
418
 * VGA init
 
419
 ****************************************************************/
 
420
 
 
421
// Call into vga code to turn on console.
 
422
void
 
423
vga_setup(void)
 
424
{
 
425
    VGAbdf = -1;
 
426
    RomEnd = BUILD_ROM_START;
 
427
 
 
428
    if (! CONFIG_OPTIONROMS)
 
429
        return;
 
430
 
 
431
    dprintf(1, "Scan for VGA option rom\n");
 
432
 
 
433
    if (CONFIG_OPTIONROMS_DEPLOYED) {
 
434
        // Option roms are already deployed on the system.
 
435
        init_optionrom((void*)BUILD_ROM_START, 0, 1);
 
436
    } else {
 
437
        // Find and deploy PCI VGA rom.
 
438
        int bdf = VGAbdf = pci_find_vga();
 
439
        if (bdf >= 0)
 
440
            init_pcirom(bdf, 1);
 
441
 
 
442
        // Find and deploy CBFS vga-style roms not associated with a device.
 
443
        run_file_roms("vgaroms/", 1);
 
444
    }
 
445
 
 
446
    if (RomEnd == BUILD_ROM_START) {
 
447
        // No VGA rom found
 
448
        RomEnd += OPTION_ROM_ALIGN;
 
449
        return;
 
450
    }
 
451
 
 
452
    enable_vga_console();
 
453
}
 
454
 
 
455
void
 
456
s3_resume_vga_init(void)
 
457
{
 
458
    if (!CONFIG_S3_RESUME_VGA_INIT)
 
459
        return;
 
460
    struct rom_header *rom = (void*)BUILD_ROM_START;
 
461
    if (! is_valid_rom(rom))
 
462
        return;
 
463
    callrom(rom, 0);
 
464
}