xref: /qemu/hw/xen/xen_pt_load_rom.c (revision 6dad8260)
1ab37bfc7SPaolo Bonzini /*
2ab37bfc7SPaolo Bonzini  * This is splited from hw/i386/kvm/pci-assign.c
3ab37bfc7SPaolo Bonzini  */
4ab37bfc7SPaolo Bonzini #include "qemu/osdep.h"
5ab37bfc7SPaolo Bonzini #include "qapi/error.h"
6ab37bfc7SPaolo Bonzini #include "hw/hw.h"
7ab37bfc7SPaolo Bonzini #include "hw/i386/pc.h"
8ab37bfc7SPaolo Bonzini #include "qemu/error-report.h"
9ab37bfc7SPaolo Bonzini #include "ui/console.h"
10ab37bfc7SPaolo Bonzini #include "hw/loader.h"
11ab37bfc7SPaolo Bonzini #include "monitor/monitor.h"
12ab37bfc7SPaolo Bonzini #include "qemu/range.h"
13ab37bfc7SPaolo Bonzini #include "sysemu/sysemu.h"
14ab37bfc7SPaolo Bonzini #include "hw/pci/pci.h"
15ab37bfc7SPaolo Bonzini #include "xen_pt.h"
16ab37bfc7SPaolo Bonzini 
17ab37bfc7SPaolo Bonzini /*
18ab37bfc7SPaolo Bonzini  * Scan the assigned devices for the devices that have an option ROM, and then
19ab37bfc7SPaolo Bonzini  * load the corresponding ROM data to RAM. If an error occurs while loading an
20ab37bfc7SPaolo Bonzini  * option ROM, we just ignore that option ROM and continue with the next one.
21ab37bfc7SPaolo Bonzini  */
22*6dad8260SPeter Maydell void *pci_assign_dev_load_option_rom(PCIDevice *dev,
23ab37bfc7SPaolo Bonzini                                      int *size, unsigned int domain,
24ab37bfc7SPaolo Bonzini                                      unsigned int bus, unsigned int slot,
25ab37bfc7SPaolo Bonzini                                      unsigned int function)
26ab37bfc7SPaolo Bonzini {
27ab37bfc7SPaolo Bonzini     char name[32], rom_file[64];
28ab37bfc7SPaolo Bonzini     FILE *fp;
29ab37bfc7SPaolo Bonzini     uint8_t val;
30ab37bfc7SPaolo Bonzini     struct stat st;
31ab37bfc7SPaolo Bonzini     void *ptr = NULL;
32*6dad8260SPeter Maydell     Object *owner = OBJECT(dev);
33ab37bfc7SPaolo Bonzini 
34ab37bfc7SPaolo Bonzini     /* If loading ROM from file, pci handles it */
35ab37bfc7SPaolo Bonzini     if (dev->romfile || !dev->rom_bar) {
36ab37bfc7SPaolo Bonzini         return NULL;
37ab37bfc7SPaolo Bonzini     }
38ab37bfc7SPaolo Bonzini 
39ab37bfc7SPaolo Bonzini     snprintf(rom_file, sizeof(rom_file),
40ab37bfc7SPaolo Bonzini              "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/rom",
41ab37bfc7SPaolo Bonzini              domain, bus, slot, function);
42ab37bfc7SPaolo Bonzini 
43ab37bfc7SPaolo Bonzini     /* Write "1" to the ROM file to enable it */
44ab37bfc7SPaolo Bonzini     fp = fopen(rom_file, "r+");
45ab37bfc7SPaolo Bonzini     if (fp == NULL) {
46ab37bfc7SPaolo Bonzini         if (errno != ENOENT) {
47ab37bfc7SPaolo Bonzini             error_report("pci-assign: Cannot open %s: %s", rom_file, strerror(errno));
48ab37bfc7SPaolo Bonzini         }
49ab37bfc7SPaolo Bonzini         return NULL;
50ab37bfc7SPaolo Bonzini     }
51ab37bfc7SPaolo Bonzini     if (fstat(fileno(fp), &st) == -1) {
52ab37bfc7SPaolo Bonzini         error_report("pci-assign: Cannot stat %s: %s", rom_file, strerror(errno));
53ab37bfc7SPaolo Bonzini         goto close_rom;
54ab37bfc7SPaolo Bonzini     }
55ab37bfc7SPaolo Bonzini 
56ab37bfc7SPaolo Bonzini     val = 1;
57ab37bfc7SPaolo Bonzini     if (fwrite(&val, 1, 1, fp) != 1) {
58ab37bfc7SPaolo Bonzini         goto close_rom;
59ab37bfc7SPaolo Bonzini     }
60ab37bfc7SPaolo Bonzini     fseek(fp, 0, SEEK_SET);
61ab37bfc7SPaolo Bonzini 
62ab37bfc7SPaolo Bonzini     snprintf(name, sizeof(name), "%s.rom", object_get_typename(owner));
63*6dad8260SPeter Maydell     memory_region_init_ram(&dev->rom, owner, name, st.st_size, &error_abort);
64ab37bfc7SPaolo Bonzini     ptr = memory_region_get_ram_ptr(&dev->rom);
65ab37bfc7SPaolo Bonzini     memset(ptr, 0xff, st.st_size);
66ab37bfc7SPaolo Bonzini 
67ab37bfc7SPaolo Bonzini     if (!fread(ptr, 1, st.st_size, fp)) {
68ab37bfc7SPaolo Bonzini         error_report("pci-assign: Cannot read from host %s", rom_file);
69ab37bfc7SPaolo Bonzini         error_printf("Device option ROM contents are probably invalid "
70ab37bfc7SPaolo Bonzini                      "(check dmesg).\nSkip option ROM probe with rombar=0, "
71ab37bfc7SPaolo Bonzini                      "or load from file with romfile=\n");
72ab37bfc7SPaolo Bonzini         goto close_rom;
73ab37bfc7SPaolo Bonzini     }
74ab37bfc7SPaolo Bonzini 
75ab37bfc7SPaolo Bonzini     pci_register_bar(dev, PCI_ROM_SLOT, 0, &dev->rom);
76ab37bfc7SPaolo Bonzini     dev->has_rom = true;
77ab37bfc7SPaolo Bonzini     *size = st.st_size;
78ab37bfc7SPaolo Bonzini close_rom:
79ab37bfc7SPaolo Bonzini     /* Write "0" to disable ROM */
80ab37bfc7SPaolo Bonzini     fseek(fp, 0, SEEK_SET);
81ab37bfc7SPaolo Bonzini     val = 0;
82ab37bfc7SPaolo Bonzini     if (!fwrite(&val, 1, 1, fp)) {
83ab37bfc7SPaolo Bonzini         XEN_PT_WARN(dev, "%s\n", "Failed to disable pci-sysfs rom file");
84ab37bfc7SPaolo Bonzini     }
85ab37bfc7SPaolo Bonzini     fclose(fp);
86ab37bfc7SPaolo Bonzini 
87ab37bfc7SPaolo Bonzini     return ptr;
88ab37bfc7SPaolo Bonzini }
89