Currently pci_bar_is_valid() returns the value stored in a BAR. That is wrong, because the function fails if the returned value is zero. But that is wrong, because: - an address in PIO address space may be zero; - an upper part of 64-bit BAR may be zero; The right way of validating a BAR is checking its size - for implemented BARs the size is non-zero. It might look strange, but the function checks not just the queried BAR, but sanity of all six BARs of the device. If we checked only requested BAR the function could have succeeded with inconsistent BAR sizes combinations. I.e. imagine a corrupted BARs reported by a device: BAR 0 - 64 bit lower BAR 1 - 64 bit lower BAR 2 - 64 bit upper ... If the function is asked about BAR 1 it would succeed, even though in fact the layout is ambiguous. As result, the function is expected to be called only with valid BAR numbers and BARs layout should be consistent. Otherwise, an assert is raised. The BAR number parameter bar_num is only allowed to refer a 32-bit BAR or lower part of a 64-bit BAR, as it does not make sense checking validity of high part of a 64-bit BAR. Thus, the caller is expected to know the device BARs layout. Cc: Thomas Huth <thuth@xxxxxxxxxx> Cc: Andrew Jones <drjones@xxxxxxxxxx> Signed-off-by: Alexander Gordeev <agordeev@xxxxxxxxxx> --- lib/pci.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/pci.c b/lib/pci.c index fdd88296f0ae..00fba6e07860 100644 --- a/lib/pci.c +++ b/lib/pci.c @@ -117,7 +117,24 @@ bool pci_bar_is_memory(pcidevaddr_t dev, int bar_num) bool pci_bar_is_valid(pcidevaddr_t dev, int bar_num) { - return pci_bar_get(dev, bar_num); + bool is64 = false; + int i; + + assert(bar_num >= 0 && bar_num < 6); + + for (i = 0; i < 6; i++) { + if (is64) { + assert(i == bar_num); /* high part of 64-bit BAR */ + assert(pci_bar_is64(dev, i)); + + is64 = false; + } else { + is64 = pci_bar_is64(dev, i); + } + } + assert(!is64); /* incomplete 64-bit BAR */ + + return pci_bar_size(dev, bar_num); } bool pci_bar_is64(pcidevaddr_t dev, int bar_num) -- 1.8.3.1