Index: b/ChangeLog =================================================================== --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +* Fri Jan 18 2013 +- Add version number to biosdevname +- Save off Secondary PCI bus for PCI tree traversal +- Change scan of SMBIOS slot <-> PCI mapping + * Mon Jul 1 2012 - Use addslot() to track both embedded and physical index per slot - Add fixes to ignore NPAR parsing on some cards Index: b/Makefile.am =================================================================== --- a/Makefile.am +++ b/Makefile.am @@ -6,7 +6,7 @@ dist_noinst_DATA = biosdevname.rules.in -CLEANFILES = version +CLEANFILES = version src/version.h install-data-local: mkdir -p $(DESTDIR)@RULEDIR@ $(INSTALL_DATA) $(top_srcdir)/biosdevname.rules.in $(DESTDIR)@RULEDEST@ Index: b/configure.ac =================================================================== --- a/configure.ac +++ b/configure.ac @@ -88,5 +88,5 @@ echo "PACKAGE_NAME='$PACKAGE_NAME'" > ve echo "PACKAGE_VERSION='$PACKAGE_VERSION'" >> version echo "PACKAGE_STRING='$PACKAGE_STRING'" >> version -AC_CONFIG_FILES([Makefile biosdevname.spec.fedora biosdevname.spec.suse]) +AC_CONFIG_FILES([Makefile biosdevname.spec.fedora biosdevname.spec.suse src/version.h]) AC_OUTPUT Index: b/src/bios_dev_name.c =================================================================== --- a/src/bios_dev_name.c +++ b/src/bios_dev_name.c @@ -10,6 +10,8 @@ #include #include +#include "version.h" + #include "libbiosdevname.h" #include "bios_dev_name.h" @@ -29,6 +31,7 @@ static void usage(void) fprintf(stderr, " --prefix [string] string use for embedded NICs (default='em')\n"); fprintf(stderr, " --smbios [x.y] Require SMBIOS x.y or greater\n"); fprintf(stderr, " --nopirq Don't use $PIR table for slot numbers\n"); + fprintf(stderr, " --version Show biosdevname version\n"); fprintf(stderr, " Example: biosdevname -i eth0\n"); fprintf(stderr, " returns: em1\n"); fprintf(stderr, " when eth0 is an embedded NIC with label '1' on the chassis.\n"); @@ -63,6 +66,7 @@ parse_opts(int argc, char **argv) {"prefix", required_argument, 0, 'P'}, {"nopirq", no_argument, 0, 'x'}, {"smbios", required_argument, 0, 's'}, + {"version", no_argument, 0, 'v'}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, @@ -89,6 +93,9 @@ parse_opts(int argc, char **argv) case 'x': nopirq = 1; break; + case 'v': + fprintf(stderr, "biosdevname version %s\n", BIOSDEVNAME_VERSION); + exit(0); default: usage(); exit(1); Index: b/src/dmidecode/dmidecode.c =================================================================== --- a/src/dmidecode/dmidecode.c +++ b/src/dmidecode/dmidecode.c @@ -42,6 +42,12 @@ extern int smver_mjr, smver_mnr, is_valid_smbios; +#ifdef DEBUG +#define dprintf printf +#else +#define dprintf(a...) +#endif + static const char *bad_index = ""; /* @@ -93,37 +99,78 @@ static void strip_right(char *s) } } -static void fill_one_slot_function(struct pci_device *pdev, struct dmi_header *h) +static int matchpci(struct pci_device *pdev, int domain, int bus, int device, int func) { - u8 *data = h->data; - pdev->physical_slot = WORD(data+0x09); - pdev->smbios_type = 0; - pdev->smbios_instance = 0; - pdev->uses_smbios |= HAS_SMBIOS_SLOT; - if (dmi_string(h, data[0x04])) { - pdev->smbios_label=strdup(dmi_string(h, data[0x04])); - pdev->uses_smbios |= HAS_SMBIOS_LABEL; - } - strip_right(pdev->smbios_label); + if (domain != -1 && pdev->pci_dev->domain != domain) + return 0; + if (bus != -1 && pdev->pci_dev->bus != bus) + return 0; + if (device != -1 && pdev->pci_dev->dev != device) + return 0; + if (func != -1 && pdev->pci_dev->func != func) + return 0; + return 1; } -static void fill_all_slot_functions(const struct libbiosdevname_state *state, int domain, int bus, int device, struct dmi_header *h) +int smbios_setslot(const struct libbiosdevname_state *state, + int domain, int bus, int device, int func, + int type, int slot, int index, const char *label) { - struct pci_device *pdev; + struct pci_device *pdev, *n; + int i; + + dprintf("setslot: %.4x:%.2x:%.2x.%x = slot(%2d %2d) %s\n", + domain, bus, device, func, slot, index, label); + + /* Don't bother with disabled devices */ + if ((bus == 0 && device == 0 && func == 0) || /* bug on HP systems */ + (bus == 0xFF && device == 0x1F && func == 0x7)) + { + dprintf("disabled\n"); + return; + } + list_for_each_entry(pdev, &state->pci_devices, node) { - if (pdev->pci_dev->domain == domain && - pdev->pci_dev->bus == bus && - pdev->pci_dev->dev == device && - ! (pdev->uses_smbios & HAS_SMBIOS_EXACT_MATCH)) - fill_one_slot_function(pdev, h); + if (!matchpci(pdev, domain, bus, device, func)) + continue; + + dprintf(" found device: %.4x:%.2x:%.2x.%x = %lx\n", + pdev->pci_dev->domain, pdev->pci_dev->bus, pdev->pci_dev->dev, + pdev->pci_dev->func, pdev->class); + + pdev->uses_smbios |= HAS_SMBIOS_SLOT; + if (index != 0) + pdev->uses_smbios |= HAS_SMBIOS_INSTANCE; + pdev->smbios_type = type; + pdev->smbios_enabled = 1; + pdev->smbios_instance = index; + + pdev->physical_slot = slot; + if (label) { + pdev->smbios_label = strdup(label); + pdev->uses_smbios |= HAS_SMBIOS_LABEL; + strip_right(pdev->smbios_label); + } + + /* Found a PDEV, now is it a bridge? */ + if (pdev->sbus == -1) + continue; + dprintf("scan subbus: %d\n", pdev->sbus); + list_for_each_entry(n, &state->pci_devices, node) { + if (matchpci(n, domain, pdev->sbus, -1, -1)) { + smbios_setslot(state, n->pci_dev->domain, n->pci_dev->bus, + n->pci_dev->dev, n->pci_dev->func, + type, slot, index, label); + } + } + dprintf("done subbus: %d\n", pdev->sbus); } } static void dmi_decode(struct dmi_header *h, u16 ver, const struct libbiosdevname_state *state) { u8 *data=h->data; - int domain, bus, device, function; - struct pci_device *pdev; + int domain, bus, device, function, i; switch(h->type) { case 9: /* 3.3.10 System Slots */ @@ -132,16 +179,15 @@ static void dmi_decode(struct dmi_header bus = data[0x0F]; device = (data[0x10]>>3)&0x1F; function = data[0x10] & 7; - if (! (domain == 0xFFFF && bus == 0xFF && data[0x10] == 0xFF)) { - device = (data[0x10]>>3)&0x1F; - function = data[0x10] & 7; - pdev = find_pci_dev_by_pci_addr(state, domain, bus, device, function); - if (pdev) { - fill_one_slot_function(pdev, h); - pdev->uses_smbios |= HAS_SMBIOS_EXACT_MATCH; + if (domain != 0xFFFF) { + for (i=0; i<8; i++) + smbios_setslot(state, domain, bus, device, i, + 0x00, WORD(data+0x09), 0x00, + dmi_string(h, data[0x04])); } - fill_all_slot_functions(state, domain, bus, device, h); } + else { + dprintf("Old Slot: id:%3d, type:%.2x, label:%-7s\n", WORD(data+0x09), data[0x05], dmi_string(h, data[0x04])); } break; case 41: /* 3.3.xx Onboard Device Information */ @@ -149,18 +195,12 @@ static void dmi_decode(struct dmi_header bus = data[0x09]; device = (data[0xa]>>3) & 0x1F; function = data[0xa] & 0x7; - pdev = find_pci_dev_by_pci_addr(state, domain, bus, device, function); - if (pdev) { - pdev->physical_slot = 0; - pdev->smbios_enabled = !!(data[0x05] & 0x80); - pdev->smbios_type = data[0x05] & 0x7F; - pdev->smbios_instance = data[0x06]; - pdev->uses_smbios |= HAS_SMBIOS_INSTANCE | HAS_SMBIOS_SLOT; - if (dmi_string(h, data[0x04])) { - pdev->smbios_label=strdup(dmi_string(h, data[0x04])); - pdev->uses_smbios |= HAS_SMBIOS_LABEL; - } - strip_right(pdev->smbios_label); + + if (data[5] == (0x80 | 0x05)) { + // enabled and type == ethernet + smbios_setslot(state, domain, bus, device, function, + data[5] & 0x7F, 0x00, data[0x06], + dmi_string(h, data[0x04])); } break; Index: b/src/dmidecode/dmidecode.h =================================================================== --- a/src/dmidecode/dmidecode.h +++ b/src/dmidecode/dmidecode.h @@ -66,3 +66,6 @@ enum dmi_onboard_device_type { struct libbiosdevname_state; int dmidecode_main(const struct libbiosdevname_state *state); +int smbios_setslot(const struct libbiosdevname_state *state, + int domain, int bus, int device, int func, + int type, int slot, int index, const char *label); Index: b/src/dmidecode/dmioem.c =================================================================== --- a/src/dmidecode/dmioem.c +++ b/src/dmidecode/dmioem.c @@ -58,21 +58,16 @@ static int dmi_decode_hp(struct dmi_head int nic, ptr; u8 smbios_type = 0; u8 bus, device, func; - struct pci_device *pdev; switch(h->type) { case 209: - case 221: /* * Vendor Specific: HP ProLiant NIC MAC Information * * This prints the BIOS NIC number, * PCI bus/device/function, and MAC address */ - if (h->type == 221) - smbios_type=0; - else smbios_type=0x05; nic=1; @@ -82,20 +77,11 @@ static int dmi_decode_hp(struct dmi_head bus = data[ptr+1]; device = data[ptr]>>3; func = data[ptr]&7; - pdev = find_pci_dev_by_pci_addr(state, 0, bus, device, func); - if (pdev) { - if((data[ptr]==0x00 && data[ptr+1]==0x00) || - (data[ptr]==0xFF && data[ptr+1]==0xFF)) - pdev->smbios_enabled = 0; - else { - pdev->smbios_enabled = 1; - pdev->smbios_type = smbios_type; - pdev->smbios_instance = nic; - pdev->physical_slot = 0; - } - } + + smbios_setslot(state, 0, bus, device, func, smbios_type, 0, nic, NULL); + nic++; - ptr+=8; + ptr += 8; } break; Index: b/src/pci.c =================================================================== --- a/src/pci.c +++ b/src/pci.c @@ -585,6 +585,7 @@ static void add_pci_dev(struct libbiosde struct pci_dev *p) { struct pci_device *dev; + uint8_t hdr; dev = malloc(sizeof(*dev)); if (!dev) { fprintf(stderr, "out of memory\n"); @@ -603,6 +604,18 @@ static void add_pci_dev(struct libbiosde dev->vpd_pf = NULL; fill_pci_dev_sysfs(dev, p); list_add(&dev->node, &state->pci_devices); + + /* Get subordinate bus if this is a bridge */ + hdr = pci_read_byte(p, PCI_HEADER_TYPE); + switch (hdr & 0x7F) { + case PCI_HEADER_TYPE_BRIDGE: + case PCI_HEADER_TYPE_CARDBUS: + dev->sbus = pci_read_byte(p, PCI_SECONDARY_BUS); + break; + default: + dev->sbus = -1; + break; + } } void free_pci_devices(struct libbiosdevname_state *state) Index: b/src/pci.h =================================================================== --- a/src/pci.h +++ b/src/pci.h @@ -27,6 +27,7 @@ struct pci_device { unsigned int index_in_slot; /* only valid if physical_slot > 0 and not a VF */ unsigned int embedded_index; /* only valid if embedded_index_valid */ unsigned short int class; + unsigned int sbus; unsigned char uses_smbios; unsigned char smbios_type; unsigned char smbios_instance; Index: b/src/version.h.in =================================================================== --- /dev/null +++ b/src/version.h.in @@ -0,0 +1 @@ +#define BIOSDEVNAME_VERSION "@PACKAGE_VERSION@"