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