File verify-network-VPD of Package biosdevname

X-Git-Url: http://linux.dell.com/cgi-bin/gitweb/gitweb.cgi?p=biosdevname.git;a=blobdiff_plain;f=src%2Fpci.c;h=2175c87f815b33af09bd00d00387d0cec22cd993;hp=7220afc24753c83152acf2ae13b8f1529505a18b;hb=199c98f7bf3ae05f3ecdefcaa776278e7c535cba;hpb=473634364dbc28573faff4ab27d637f7fc842e74

diff --git a/src/pci.c b/src/pci.c
index 7220afc..2175c87 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -45,6 +45,32 @@ static inline u8 pci_vpd_info_field_size(const u8 *info_field)
 	return info_field[2];
 }
 
+static int pci_vpd_size(struct pci_device *pdev, int fd)
+{
+	uint8_t buf[3], tag;
+	int off;
+
+	if (!is_pci_network(pdev))
+		return 0;
+	off = 0;
+	for(;;) {
+		if (pread(fd, buf, 1, off) != 1)
+			break;
+		if (buf[0] & PCI_VPD_LRDT) {
+			tag = buf[0];
+			if (pread(fd, buf, 3, off) != 3)
+				break;
+			off += PCI_VPD_LRDT_TAG_SIZE + pci_vpd_lrdt_size(buf);
+		} else {
+			tag = buf[0] & ~PCI_VPD_SRDT_LEN_MASK;
+			off += PCI_VPD_SRDT_TAG_SIZE + pci_vpd_srdt_size(buf);
+		}
+		if (tag == 0 || tag == 0xFF || tag == PCI_VPD_SRDT_END)
+			break;
+	}
+	return off;
+}
+
 static int pci_vpd_find_tag(const u8 *buf, unsigned int off, unsigned int len, u8 rdt)
 {
 	int i;
@@ -147,12 +173,14 @@ static int read_pci_vpd(struct pci_device *pdev)
 	unparse_pci_name(pci_name, sizeof(pci_name), pdev->pci_dev);
 	snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/vpd", pci_name);
 	if ((fd = open(path, O_RDONLY)) >= 0) {
-		size = lseek(fd, 0, SEEK_END);
-		vpd  = malloc(size);
-		if (vpd != NULL) {
-			if ((nrd = pread(fd, vpd, size, 0)) > 0)
-				rc = parse_vpd(pdev, nrd, vpd);
-			free(vpd);
+		size = pci_vpd_size(pdev, fd);
+		if (size > 0) {
+		        vpd = malloc(size);
+			if (vpd != NULL) {
+				if ((nrd = pread(fd, vpd, size, 0)) > 0)
+					rc = parse_vpd(pdev, nrd, vpd);
+				free(vpd);
+			}
 		}
 		close(fd);
 	}
openSUSE Build Service is sponsored by