diff --git a/src/linux_sysfs.c b/src/linux_sysfs.c index 8c3cf67..2ea78c1 100644 --- a/src/linux_sysfs.c +++ b/src/linux_sysfs.c @@ -227,6 +227,7 @@ pci_device_linux_sysfs_probe( struct pci_device * dev ) pciaddr_t bytes; unsigned i; int err; + struct stat st; err = pci_device_linux_sysfs_read( dev, config, 0, 256, & bytes ); @@ -293,11 +294,28 @@ pci_device_linux_sysfs_probe( struct pci_device * dev ) flags = strtoull( next, & next, 16 ); if ( low_addr != 0 ) { priv->rom_base = low_addr; - dev->rom_size = (high_addr - low_addr) + 1; } } } + snprintf( name, 255, "%s/%04x:%02x:%02x.%1u/rom", + SYS_BUS_PCI, + dev->domain, + dev->bus, + dev->dev, + dev->func ); + + fd = open( name, O_RDWR ); + if ( fd == -1 ) { + dev->rom_size = 0x10000; + } else if ( fstat( fd, & st ) == -1 ) { + close( fd ); + dev->rom_size = 0x10000; + } else { + close( fd ); + dev->rom_size = st.st_size == 0 ? 0x10000 : st.st_size; + } + return err; } @@ -309,7 +327,6 @@ pci_device_linux_sysfs_read_rom( struct pci_device * dev, void * buffer ) int fd; struct stat st; int err = 0; - size_t rom_size; size_t total_bytes; @@ -334,10 +351,6 @@ pci_device_linux_sysfs_read_rom( struct pci_device * dev, void * buffer ) return errno; } - rom_size = st.st_size; - if ( rom_size == 0 ) - rom_size = 0x10000; - /* This is a quirky thing on Linux. Even though the ROM and the file * for the ROM in sysfs are read-only, the string "1" must be written to * the file to enable the ROM. After the data has been read, "0" must be @@ -346,9 +359,9 @@ pci_device_linux_sysfs_read_rom( struct pci_device * dev, void * buffer ) write( fd, "1", 1 ); lseek( fd, 0, SEEK_SET ); - for ( total_bytes = 0 ; total_bytes < rom_size ; /* empty */ ) { + for ( total_bytes = 0 ; total_bytes < dev->rom_size ; /* empty */ ) { const int bytes = read( fd, (char *) buffer + total_bytes, - rom_size - total_bytes ); + dev->rom_size - total_bytes ); if ( bytes == -1 ) { err = errno; break;