Revision ab85ceb1
b/hw/pci.c | ||
---|---|---|
61 | 61 |
|
62 | 62 |
static void pci_update_mappings(PCIDevice *d); |
63 | 63 |
static void pci_set_irq(void *opaque, int irq_num, int level); |
64 |
static int pci_add_option_rom(PCIDevice *pdev); |
|
64 |
static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
|
|
65 | 65 |
static void pci_del_option_rom(PCIDevice *pdev); |
66 | 66 |
|
67 | 67 |
static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET; |
... | ... | |
1571 | 1571 |
PCIDeviceInfo *info = container_of(base, PCIDeviceInfo, qdev); |
1572 | 1572 |
PCIBus *bus; |
1573 | 1573 |
int devfn, rc; |
1574 |
bool is_default_rom; |
|
1574 | 1575 |
|
1575 | 1576 |
/* initialize cap_present for pci_is_express() and pci_config_size() */ |
1576 | 1577 |
if (info->is_express) { |
... | ... | |
1591 | 1592 |
} |
1592 | 1593 |
|
1593 | 1594 |
/* rom loading */ |
1594 |
if (pci_dev->romfile == NULL && info->romfile != NULL) |
|
1595 |
is_default_rom = false; |
|
1596 |
if (pci_dev->romfile == NULL && info->romfile != NULL) { |
|
1595 | 1597 |
pci_dev->romfile = qemu_strdup(info->romfile); |
1596 |
pci_add_option_rom(pci_dev); |
|
1598 |
is_default_rom = true; |
|
1599 |
} |
|
1600 |
pci_add_option_rom(pci_dev, is_default_rom); |
|
1597 | 1601 |
|
1598 | 1602 |
if (bus->hotplug) { |
1599 | 1603 |
/* Let buses differentiate between hotplug and when device is |
... | ... | |
1701 | 1705 |
cpu_register_physical_memory(addr, size, pdev->rom_offset); |
1702 | 1706 |
} |
1703 | 1707 |
|
1708 |
/* Patch the PCI vendor and device ids in a PCI rom image if necessary. |
|
1709 |
This is needed for an option rom which is used for more than one device. */ |
|
1710 |
static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size) |
|
1711 |
{ |
|
1712 |
uint16_t vendor_id; |
|
1713 |
uint16_t device_id; |
|
1714 |
uint16_t rom_vendor_id; |
|
1715 |
uint16_t rom_device_id; |
|
1716 |
uint16_t rom_magic; |
|
1717 |
uint16_t pcir_offset; |
|
1718 |
uint8_t checksum; |
|
1719 |
|
|
1720 |
/* Words in rom data are little endian (like in PCI configuration), |
|
1721 |
so they can be read / written with pci_get_word / pci_set_word. */ |
|
1722 |
|
|
1723 |
/* Only a valid rom will be patched. */ |
|
1724 |
rom_magic = pci_get_word(ptr); |
|
1725 |
if (rom_magic != 0xaa55) { |
|
1726 |
PCI_DPRINTF("Bad ROM magic %04x\n", rom_magic); |
|
1727 |
return; |
|
1728 |
} |
|
1729 |
pcir_offset = pci_get_word(ptr + 0x18); |
|
1730 |
if (pcir_offset + 8 >= size || memcmp(ptr + pcir_offset, "PCIR", 4)) { |
|
1731 |
PCI_DPRINTF("Bad PCIR offset 0x%x or signature\n", pcir_offset); |
|
1732 |
return; |
|
1733 |
} |
|
1734 |
|
|
1735 |
vendor_id = pci_get_word(pdev->config + PCI_VENDOR_ID); |
|
1736 |
device_id = pci_get_word(pdev->config + PCI_DEVICE_ID); |
|
1737 |
rom_vendor_id = pci_get_word(ptr + pcir_offset + 4); |
|
1738 |
rom_device_id = pci_get_word(ptr + pcir_offset + 6); |
|
1739 |
|
|
1740 |
PCI_DPRINTF("%s: ROM id %04x%04x / PCI id %04x%04x\n", pdev->romfile, |
|
1741 |
vendor_id, device_id, rom_vendor_id, rom_device_id); |
|
1742 |
|
|
1743 |
checksum = ptr[6]; |
|
1744 |
|
|
1745 |
if (vendor_id != rom_vendor_id) { |
|
1746 |
/* Patch vendor id and checksum (at offset 6 for etherboot roms). */ |
|
1747 |
checksum += (uint8_t)rom_vendor_id + (uint8_t)(rom_vendor_id >> 8); |
|
1748 |
checksum -= (uint8_t)vendor_id + (uint8_t)(vendor_id >> 8); |
|
1749 |
PCI_DPRINTF("ROM checksum %02x / %02x\n", ptr[6], checksum); |
|
1750 |
ptr[6] = checksum; |
|
1751 |
pci_set_word(ptr + pcir_offset + 4, vendor_id); |
|
1752 |
} |
|
1753 |
|
|
1754 |
if (device_id != rom_device_id) { |
|
1755 |
/* Patch device id and checksum (at offset 6 for etherboot roms). */ |
|
1756 |
checksum += (uint8_t)rom_device_id + (uint8_t)(rom_device_id >> 8); |
|
1757 |
checksum -= (uint8_t)device_id + (uint8_t)(device_id >> 8); |
|
1758 |
PCI_DPRINTF("ROM checksum %02x / %02x\n", ptr[6], checksum); |
|
1759 |
ptr[6] = checksum; |
|
1760 |
pci_set_word(ptr + pcir_offset + 6, device_id); |
|
1761 |
} |
|
1762 |
} |
|
1763 |
|
|
1704 | 1764 |
/* Add an option rom for the device */ |
1705 |
static int pci_add_option_rom(PCIDevice *pdev) |
|
1765 |
static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
|
|
1706 | 1766 |
{ |
1707 | 1767 |
int size; |
1708 | 1768 |
char *path; |
... | ... | |
1753 | 1813 |
load_image(path, ptr); |
1754 | 1814 |
qemu_free(path); |
1755 | 1815 |
|
1816 |
if (is_default_rom) { |
|
1817 |
/* Only the default rom images will be patched (if needed). */ |
|
1818 |
pci_patch_ids(pdev, ptr, size); |
|
1819 |
} |
|
1820 |
|
|
1756 | 1821 |
pci_register_bar(pdev, PCI_ROM_SLOT, size, |
1757 | 1822 |
0, pci_map_option_rom); |
1758 | 1823 |
|
Also available in: Unified diff