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>