#define VPD_FIELD_CHECKSUM "RV"
#define VPD_FIELD_RW "RW"
-int pci_find_capability(int device, int cap_id)
+int pci_find_capability(int fd, int cap_id)
{
unsigned offset;
unsigned char visited[256] = {}; /* Prevent infinite loops */
unsigned char data[2];
int ret;
- ret = pread(device, data, 1, PCI_CAP_PTR);
- if (ret != 1)
+ ret = pread(fd, data, 1, PCI_CAP_PTR);
+ if (ret != 1) {
return 0;
+ }
offset = data[0];
for(;;) {
- if (offset < PCI_HDR_SIZE)
+ if (offset < PCI_HDR_SIZE) {
return 0;
+ }
- ret = pread(device, data, sizeof data, offset);
- if (ret != sizeof data)
+ ret = pread(fd, data, sizeof data, offset);
+ if (ret != sizeof data) {
return 0;
+ }
visited[offset] = 1;
- if (data[0] == cap_id)
+ if (data[0] == cap_id) {
return offset;
+ }
offset = data[1];
- if (visited[offset])
+ if (visited[offset]) {
return 0;
+ }
}
+ return 0;
}
-int pci_read_vpd_dword(int device, int vpd_cap_offset, unsigned offset, unsigned char data[4])
+int pci_read_vpd_dword_file(int fd, unsigned offset, unsigned char data[4])
+{
+ unsigned char addr_flag[2];
+ int ret;
+ if (offset >= VPD_MAX_SIZE || (offset & 0x3)) {
+ return -1;
+ }
+
+ if (lseek(fd, offset, SEEK_SET) < 0)
+ {
+ fprintf(stderr, "Reached End Of VPD region: %s\n", strerror(errno));
+ return errno;
+ }
+ if (read(fd, data, 0x4) != 4) {
+ fprintf(stderr, "Failed to read VPD: %s\n", strerror(errno));
+ return errno;
+ }
+ return 0;
+}
+
+int pci_read_vpd_dword_gw(int fd, int vpd_cap_offset, unsigned offset, unsigned char data[4])
{
unsigned char addr_flag[2];
int ret;
- if (offset >= VPD_MAX_SIZE || (offset & 0x3))
+ if (offset >= VPD_MAX_SIZE || (offset & 0x3)) {
return -1;
+ }
addr_flag[0] = (offset) & ~0x3;
addr_flag[1] = ((offset) >> 8) | VPD_FLAG_READ_START;
- ret = pwrite(device, addr_flag, sizeof addr_flag,
+ ret = pwrite(fd, addr_flag, sizeof addr_flag,
vpd_cap_offset + VPD_ADDR_OFFSET);
- if (ret != sizeof addr_flag)
+ if (ret != sizeof addr_flag) {
return ret;
+ }
start_t = times(NULL);
while((addr_flag[1] & VPD_FLAG) != VPD_FLAG_READ_READY) {
return -EIO;
}
- ret = pread(device, addr_flag, sizeof addr_flag,
+ ret = pread(fd, addr_flag, sizeof addr_flag,
vpd_cap_offset + VPD_ADDR_OFFSET);
- if (ret != sizeof addr_flag)
+ if (ret != sizeof addr_flag) {
return ret;
+ }
}
- ret = pread(device, data, sizeof data, vpd_cap_offset + VPD_DATA_OFFSET);
- if (ret != sizeof data)
+ ret = pread(fd, data, sizeof data, vpd_cap_offset + VPD_DATA_OFFSET);
+ if (ret != sizeof data) {
return ret;
+ }
return 0;
}
-int vpd_read(int device, vpd_t vpd)
+int vpd_read(int fd, vpd_t vpd, int vpd_path_exists)
{
- unsigned offset;
- int ret;
- int vpd_cap_offset;
- vpd_cap_offset = pci_find_capability(device, VPD_CAP_ID);
- if (!vpd_cap_offset)
- return -1;
-
- for (offset = 0; offset < VPD_MAX_SIZE; offset += 0x4) {
- ret = pci_read_vpd_dword(device, vpd_cap_offset, offset, vpd + offset);
- if (ret)
- return ret;
- }
-
- return 0;
+ if (vpd_path_exists) {
+ unsigned offset;
+ int ret;
+ for (offset = 0; offset < VPD_MAX_SIZE; offset += 0x4) {
+ ret = pci_read_vpd_dword_file(fd, offset, vpd + offset);
+ if (ret) {
+ return ret;
+ }
+ }
+ } else {
+ unsigned offset;
+ int ret;
+ int vpd_cap_offset;
+ vpd_cap_offset = pci_find_capability(fd, VPD_CAP_ID);
+ if (!vpd_cap_offset) {
+ return -1;
+ }
+
+ for (offset = 0; offset < VPD_MAX_SIZE; offset += 0x4) {
+ ret = pci_read_vpd_dword_gw(fd, vpd_cap_offset, offset, vpd + offset);
+ if (ret) {
+ return ret;
+ }
+ }
+ }
+ return 0;
}
/* Verify that keywords in R and W sections fit in length. */
unsigned i;
struct vpd_field *field;
- if (VPD_TAG_NAME(d) != VPD_TAG_R)
+ if (VPD_TAG_NAME(d) != VPD_TAG_R) {
return;
+ }
for (i = 0; i < VPD_TAG_LENGTH(d); i += 0x3 + field->length) {
field = (struct vpd_field *)(VPD_TAG_DATA(d)->bytes + i);
int i;
if (!memcmp(VPD_FIELD_CHECKSUM, field->keyword, sizeof field->keyword) ||
- !memcmp(VPD_FIELD_RW , field->keyword, sizeof field->keyword))
+ !memcmp(VPD_FIELD_RW , field->keyword, sizeof field->keyword)) {
return;
+ }
fputc(field->keyword[0], f);
fputc(field->keyword[1], f);
fputs(": ", f);
for (i = 0; i < field->length; ++i) {
- if (!field->data[i])
+ if (!field->data[i]) {
break;
+ }
fputc(field->data[i], f);
}
fputc('\n', f);
for (i = 0; i < VPD_TAG_LENGTH(d); i += 0x3 + field->length) {
field = (struct vpd_field *)(VPD_TAG_DATA(d)->bytes + i);
if (!keyword ||
- !memcmp(keyword, field->keyword, sizeof field->keyword))
+ !memcmp(keyword, field->keyword, sizeof field->keyword)) {
vpd_show_field(f, field);
+ }
}
}
unsigned i;
fputs("ID: ", f);
- for (i = 0; i < VPD_TAG_LENGTH(d); ++i)
+ for (i = 0; i < VPD_TAG_LENGTH(d); ++i) {
fputc(VPD_TAG_DATA(d)->bytes[i], f);
+ }
fputc('\n', f);
}
{
switch(VPD_TAG_NAME(d)) {
case VPD_TAG_ID:
- if (!keyword || !memcmp("ID", keyword, 2))
+ if (!keyword || !memcmp("ID", keyword, 2)) {
vpd_show_id(f, d);
+ }
break;
case VPD_TAG_R:
vpd_show_fields(f, d, keyword);
case VPD_TAG_F:
break;
default:
- if (!keyword)
+ if (!keyword) {
fprintf(f, "??: 0x%x\n", VPD_TAG_NAME(d));
+ }
}
}
if (!(VPD_TAG_NAME(d) == VPD_TAG_W && ignore_w)) {
rc = vpd_check_one(d, offset);
- if (rc)
+ if (rc) {
return rc;
+ }
}
vpd_checksum_length(d, offset, &checksum_len);
return 1;
}
- if (!checksum)
+ if (!checksum) {
return 0;
+ }
if (!checksum_len) {
fprintf(stderr, "-E- Mandatory checksum(RV) field not found.\n");
}
b = 0;
- for (i = 0; i < checksum_len; ++i)
+ for (i = 0; i < checksum_len; ++i) {
b+= vpd[i];
+ }
if (b) {
fprintf(stderr, "-E- Len 0x%x: checksum mismatch: 0x%x\n",
}
}
-int pci_parse_name(const char *name, char buf[4096])
+int is_file_exist(const char *fname)
+{
+ int fd = open(fname, O_RDONLY);
+ if (fd > 0) {
+ u_int8_t data[4];
+ if (read(fd, data, 0x4) != 4){
+ close(fd);
+ return 0;
+ } else {
+ close(fd);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int pci_parse_name(const char *name, char buf[4096], int* vpd_path_exists)
{
int domain, bus, dev, func, tmp;
struct stat dummybuf;
}
base = basename(pbuf);
- if (!base)
+ if (!base) {
return 1;
- if (sscanf(base, "%x:%x:%x.%x", &domain, &bus, &dev, &func) != 4)
+ }
+ if (sscanf(base, "%x:%x:%x.%x", &domain, &bus, &dev, &func) != 4) {
return 1;
+ }
} else if (sscanf(name, "%x:%x:%x.%x", &domain, &bus, &dev, &func) != 4) {
domain = 0;
if (sscanf(name, "%x:%x.%x", &bus, &dev, &func) != 3)
return -2;
}
+ snprintf(buf, 4096, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/vpd", domain, bus, dev, func);
+ if (is_file_exist(buf)) {
+ *vpd_path_exists = 1;
+ return 0;
+ }
+ *vpd_path_exists = 0;
+
snprintf(buf, 4096, "/proc/bus/pci/%2.2x/%2.2x.%1.1x", bus, dev, func);
- if (stat(buf, &dummybuf))
+ if (stat(buf, &dummybuf)) {
snprintf(buf, 4096, "/proc/bus/pci/%4.4x:%2.2x/%2.2x.%1.1x",
domain, bus,dev,func);
+ }
- if (stat(buf, &dummybuf))
+ if (stat(buf, &dummybuf)) {
return -3;
+ }
return 0;
}
-int vpd_open(const char *name)
+int vpd_open(const char *name, int* vpd_path_exists)
{
int fd;
char buf[4096];
- if (pci_parse_name(name, buf)) {
+ if (pci_parse_name(name, buf, vpd_path_exists)) {
fprintf(stderr, "-E- Unable to parse device name %s\n", name);
return -1;
}
-
fd = open(buf, O_RDWR);
if (fd < 0) {
fprintf(stderr, "-E- Unable to open file %s: %s\n", buf, strerror(errno));
int m = 0;
int n = 0;
int ignore_w = 0;
+ int vpd_path_exists = 0;
if (argc < 2) {
rc = 1;
if (fread(d, VPD_MAX_SIZE, 1, stdin) != 1)
return 3;
} else {
- fd = vpd_open(name);
+ fd = vpd_open(name, &vpd_path_exists);
if (fd < 0)
return 4;
- if (vpd_read(fd, d))
+ if (vpd_read(fd, d, vpd_path_exists))
return 5;
}