Annotation of embedaddon/pciutils/ls-vpd.c, revision 1.1.1.1
1.1 misho 1: /*
2: * The PCI Utilities -- Show Vital Product Data
3: *
4: * Copyright (c) 2008 Solarflare Communications
5: *
6: * Written by Ben Hutchings <bhutchings@solarflare.com>
7: * Improved by Martin Mares <mj@ucw.cz>
8: *
9: * Can be freely distributed and used under the terms of the GNU GPL.
10: */
11:
12: #include <stdio.h>
13:
14: #include "lspci.h"
15:
16: /*
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.
20: */
21:
22: enum vpd_format {
23: F_BINARY,
24: F_TEXT,
25: F_RESVD,
26: F_RDWR,
27: };
28:
29: static const struct vpd_item {
30: byte id1, id2;
31: byte format;
32: const char *name;
33: } vpd_items[] = {
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, "Unknown" }
45: };
46:
47: static void
48: print_vpd_string(const byte *buf, word len)
49: {
50: while (len--)
51: {
52: byte ch = *buf++;
53: if (ch == '\\')
54: printf("\\\\");
55: else if (!ch && !len)
56: ; /* Cards with null-terminated strings have been observed */
57: else if (ch < 32 || ch == 127)
58: printf("\\x%02x", ch);
59: else
60: putchar(ch);
61: }
62: }
63:
64: static void
65: print_vpd_binary(const byte *buf, word len)
66: {
67: int i;
68: for (i = 0; i < len; i++)
69: {
70: if (i)
71: putchar(' ');
72: printf("%02x", buf[i]);
73: }
74: }
75:
76: static int
77: read_vpd(struct device *d, int pos, byte *buf, int len, byte *csum)
78: {
79: if (!pci_read_vpd(d->dev, pos, buf, len))
80: return 0;
81: while (len--)
82: *csum += *buf++;
83: return 1;
84: }
85:
86: void
87: cap_vpd(struct device *d)
88: {
89: word res_addr = 0, res_len, part_pos, part_len;
90: byte buf[256];
91: byte tag;
92: byte csum = 0;
93:
94: printf("Vital Product Data\n");
95: if (verbose < 2)
96: return;
97:
98: while (res_addr <= PCI_VPD_ADDR_MASK)
99: {
100: if (!read_vpd(d, res_addr, &tag, 1, &csum))
101: break;
102: if (tag & 0x80)
103: {
104: if (res_addr > PCI_VPD_ADDR_MASK + 1 - 3)
105: break;
106: if (!read_vpd(d, res_addr + 1, buf, 2, &csum))
107: break;
108: res_len = buf[0] + (buf[1] << 8);
109: res_addr += 3;
110: }
111: else
112: {
113: res_len = tag & 7;
114: tag >>= 3;
115: res_addr += 1;
116: }
117: if (res_len > PCI_VPD_ADDR_MASK + 1 - res_addr)
118: break;
119:
120: part_pos = 0;
121:
122: switch (tag)
123: {
124: case 0x0f:
125: printf("\t\tEnd\n");
126: return;
127:
128: case 0x82:
129: printf("\t\tProduct Name: ");
130: while (part_pos < res_len)
131: {
132: part_len = res_len - part_pos;
133: if (part_len > sizeof(buf))
134: part_len = sizeof(buf);
135: if (!read_vpd(d, res_addr + part_pos, buf, part_len, &csum))
136: break;
137: print_vpd_string(buf, part_len);
138: part_pos += part_len;
139: }
140: printf("\n");
141: break;
142:
143: case 0x90:
144: case 0x91:
145: printf("\t\t%s fields:\n",
146: (tag == 0x90) ? "Read-only" : "Read/write");
147:
148: while (part_pos + 3 <= res_len)
149: {
150: word read_len;
151: const struct vpd_item *item;
152: byte id1, id2;
153:
154: if (!read_vpd(d, res_addr + part_pos, buf, 3, &csum))
155: break;
156: part_pos += 3;
157: id1 = buf[0];
158: id2 = buf[1];
159: part_len = buf[2];
160: if (part_len > res_len - part_pos)
161: break;
162:
163: /* Is this item known? */
164: for (item=vpd_items; item->id1 && item->id1 != id1 ||
165: item->id2 && item->id2 != id2; item++)
166: ;
167:
168: /* Only read the first byte of the RV field because the
169: * remaining bytes are not included in the checksum. */
170: read_len = (item->format == F_RESVD) ? 1 : part_len;
171: if (!read_vpd(d, res_addr + part_pos, buf, read_len, &csum))
172: break;
173:
174: printf("\t\t\t[%c%c] %s: ", id1, id2, item->name);
175:
176: switch (item->format)
177: {
178: case F_TEXT:
179: print_vpd_string(buf, part_len);
180: printf("\n");
181: break;
182: case F_BINARY:
183: print_vpd_binary(buf, part_len);
184: printf("\n");
185: break;
186: case F_RESVD:
187: printf("checksum %s, %d byte(s) reserved\n", csum ? "bad" : "good", part_len - 1);
188: break;
189: case F_RDWR:
190: printf("%d byte(s) free\n", part_len);
191: break;
192: }
193:
194: part_pos += part_len;
195: }
196: break;
197:
198: default:
199: printf("\t\tUnknown %s resource type %02x, will not decode more.\n",
200: (tag & 0x80) ? "large" : "small", tag & ~0x80);
201: return;
202: }
203:
204: res_addr += res_len;
205: }
206:
207: if (res_addr == 0)
208: printf("\t\tNot readable\n");
209: else
210: printf("\t\tNo end tag found\n");
211: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>