2 * The PCI Utilities -- Show Vital Product Data
4 * Copyright (c) 2008 Solarflare Communications
6 * Written by Ben Hutchings <bhutchings@solarflare.com>
7 * Improved by Martin Mares <mj@ucw.cz>
9 * Can be freely distributed and used under the terms of the GNU GPL.
17 * The list of all known VPD items and their formats.
18 * Technically, this belongs to the pci.ids file, but the VPD does not seem
19 * to be developed any longer, so we have chosen the easier way.
29 static const struct vpd_item {
34 { 'C','P', F_BINARY, "Extended capability" },
35 { 'E','C', F_TEXT, "Engineering changes" },
36 { 'M','N', F_BINARY, "Manufacture ID" },
37 { 'P','N', F_TEXT, "Part number" },
38 { 'R','V', F_RESVD, "Reserved" },
39 { 'R','W', F_RDWR, "Read-write area" },
40 { 'S','N', F_TEXT, "Serial number" },
41 { 'Y','A', F_TEXT, "Asset tag" },
42 { 'V', 0 , F_TEXT, "Vendor specific" },
43 { 'Y', 0 , F_TEXT, "System specific" },
44 { 0, 0 , F_BINARY, NULL }
48 print_vpd_string(const byte *buf, word len)
55 else if (ch < 32 || ch == 127)
56 printf("\\x%02x", ch);
63 print_vpd_binary(const byte *buf, word len)
66 for (i = 0; i < len; i++)
70 printf("%02x", buf[i]);
75 read_vpd(struct device *d, int pos, byte *buf, int len, byte *csum)
77 if (!pci_read_vpd(d->dev, pos, buf, len))
85 cap_vpd(struct device *d)
87 word res_addr = 0, res_len, part_pos, part_len;
92 printf("Vital Product Data\n");
96 while (res_addr <= PCI_VPD_ADDR_MASK)
98 if (!read_vpd(d, res_addr, &tag, 1, &csum))
102 if (res_addr > PCI_VPD_ADDR_MASK + 1 - 3)
104 if (!read_vpd(d, res_addr + 1, buf, 2, &csum))
106 res_len = buf[0] + (buf[1] << 8);
115 if (res_len > PCI_VPD_ADDR_MASK + 1 - res_addr)
127 printf("\t\tProduct Name: ");
128 while (part_pos < res_len)
130 part_len = res_len - part_pos;
131 if (part_len > sizeof(buf))
132 part_len = sizeof(buf);
133 if (!read_vpd(d, res_addr + part_pos, buf, part_len, &csum))
135 print_vpd_string(buf, part_len);
136 part_pos += part_len;
143 printf("\t\t%s fields:\n",
144 (tag == 0x90) ? "Read-only" : "Read/write");
146 while (part_pos + 3 <= res_len)
149 const struct vpd_item *item;
150 struct vpd_item unknown_item;
152 if (!read_vpd(d, res_addr + part_pos, buf, 3, &csum))
156 if (part_len > res_len - part_pos)
159 /* Is this item known? */
160 for (item=vpd_items; item->id1 && item->id1 != buf[0] ||
161 item->id2 && item->id2 != buf[1]; item++)
163 if (!item->id1 && !item->id2)
165 unknown_item.id1 = buf[0];
166 unknown_item.id2 = buf[1];
167 unknown_item.format = F_BINARY;
168 unknown_item.name = "Unknown";
169 item = &unknown_item;
172 /* Only read the first byte of the RV field because the
173 * remaining bytes are not included in the checksum. */
174 read_len = (item->format == F_RESVD) ? 1 : part_len;
175 if (!read_vpd(d, res_addr + part_pos, buf, read_len, &csum))
178 printf("\t\t\t[%c%c] %s: ", item->id1, item->id2, item->name);
180 switch (item->format)
183 print_vpd_string(buf, part_len);
187 print_vpd_binary(buf, part_len);
191 printf("checksum %s, %d byte(s) reserved\n", csum ? "bad" : "good", part_len - 1);
194 printf("%d byte(s) free\n", part_len);
198 part_pos += part_len;
203 printf("\t\tUnknown %s resource type %02x\n",
204 (tag & 0x80) ? "large" : "small", tag & ~0x80);
212 printf("\t\tNot readable\n");
214 printf("\t\tNo end tag found\n");