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