Annotation of embedaddon/pciutils/lib/dump.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *     The PCI Library -- Reading of Bus Dumps
                      3:  *
                      4:  *     Copyright (c) 1997--2008 Martin Mares <mj@ucw.cz>
                      5:  *
                      6:  *     Can be freely distributed and used under the terms of the GNU GPL.
                      7:  */
                      8: 
                      9: #include <stdio.h>
                     10: #include <ctype.h>
                     11: #include <string.h>
                     12: #include <errno.h>
                     13: 
                     14: #include "internal.h"
                     15: 
                     16: struct dump_data {
                     17:   int len, allocated;
                     18:   byte data[1];
                     19: };
                     20: 
                     21: static void
                     22: dump_config(struct pci_access *a)
                     23: {
                     24:   pci_define_param(a, "dump.name", "", "Name of the bus dump file to read from");
                     25: }
                     26: 
                     27: static int
                     28: dump_detect(struct pci_access *a)
                     29: {
                     30:   char *name = pci_get_param(a, "dump.name");
                     31:   return name && name[0];
                     32: }
                     33: 
                     34: static void
                     35: dump_alloc_data(struct pci_dev *dev, int len)
                     36: {
                     37:   struct dump_data *dd = pci_malloc(dev->access, sizeof(struct dump_data) + len - 1);
                     38:   dd->allocated = len;
                     39:   dd->len = 0;
                     40:   memset(dd->data, 0xff, len);
                     41:   dev->aux = dd;
                     42: }
                     43: 
                     44: static int
                     45: dump_validate(char *s, char *fmt)
                     46: {
                     47:   while (*fmt)
                     48:     {
                     49:       if (*fmt == '#' ? !isxdigit(*s) : *fmt != *s)
                     50:        return 0;
                     51:       fmt++, s++;
                     52:     }
                     53:   return 1;
                     54: }
                     55: 
                     56: static void
                     57: dump_init(struct pci_access *a)
                     58: {
                     59:   char *name = pci_get_param(a, "dump.name");
                     60:   FILE *f;
                     61:   char buf[256];
                     62:   struct pci_dev *dev = NULL;
                     63:   int len, mn, bn, dn, fn, i, j;
                     64: 
                     65:   if (!name)
                     66:     a->error("dump: File name not given.");
                     67:   if (!(f = fopen(name, "r")))
                     68:     a->error("dump: Cannot open %s: %s", name, strerror(errno));
                     69:   while (fgets(buf, sizeof(buf)-1, f))
                     70:     {
                     71:       char *z = strchr(buf, '\n');
                     72:       if (!z)
                     73:        {
                     74:          fclose(f);
                     75:          a->error("dump: line too long or unterminated");
                     76:        }
                     77:       *z-- = 0;
                     78:       if (z >= buf && *z == '\r')
                     79:        *z-- = 0;
                     80:       len = z - buf + 1;
                     81:       mn = 0;
                     82:       if (dump_validate(buf, "##:##.# ") && sscanf(buf, "%x:%x.%d", &bn, &dn, &fn) == 3 ||
                     83:          dump_validate(buf, "####:##:##.# ") && sscanf(buf, "%x:%x:%x.%d", &mn, &bn, &dn, &fn) == 4)
                     84:        {
                     85:          dev = pci_get_dev(a, mn, bn, dn, fn);
                     86:          dump_alloc_data(dev, 256);
                     87:          pci_link_dev(a, dev);
                     88:        }
                     89:       else if (!len)
                     90:        dev = NULL;
                     91:       else if (dev &&
                     92:               (dump_validate(buf, "##: ") || dump_validate(buf, "###: ")) &&
                     93:               sscanf(buf, "%x: ", &i) == 1)
                     94:        {
                     95:          struct dump_data *dd = dev->aux;
                     96:          z = strchr(buf, ' ') + 1;
                     97:          while (isxdigit(z[0]) && isxdigit(z[1]) && (!z[2] || z[2] == ' ') &&
                     98:                 sscanf(z, "%x", &j) == 1 && j < 256)
                     99:            {
                    100:              if (i >= 4096)
                    101:                {
                    102:                  fclose(f);
                    103:                  a->error("dump: At most 4096 bytes of config space are supported");
                    104:                }
                    105:              if (i >= dd->allocated)   /* Need to re-allocate the buffer */
                    106:                {
                    107:                  dump_alloc_data(dev, 4096);
                    108:                  memcpy(((struct dump_data *) dev->aux)->data, dd->data, 256);
                    109:                  pci_mfree(dd);
                    110:                  dd = dev->aux;
                    111:                }
                    112:              dd->data[i++] = j;
                    113:              if (i > dd->len)
                    114:                dd->len = i;
                    115:              z += 2;
                    116:              if (*z)
                    117:                z++;
                    118:            }
                    119:          if (*z)
                    120:            {
                    121:              fclose(f);
                    122:              a->error("dump: Malformed line");
                    123:            }
                    124:        }
                    125:     }
                    126:   fclose(f);
                    127: }
                    128: 
                    129: static void
                    130: dump_cleanup(struct pci_access *a UNUSED)
                    131: {
                    132: }
                    133: 
                    134: static void
                    135: dump_scan(struct pci_access *a UNUSED)
                    136: {
                    137: }
                    138: 
                    139: static int
                    140: dump_read(struct pci_dev *d, int pos, byte *buf, int len)
                    141: {
                    142:   struct dump_data *dd;
                    143:   if (!(dd = d->aux))
                    144:     {
                    145:       struct pci_dev *e = d->access->devices;
                    146:       while (e && (e->domain != d->domain || e->bus != d->bus || e->dev != d->dev || e->func != d->func))
                    147:        e = e->next;
                    148:       if (!e)
                    149:        return 0;
                    150:       dd = e->aux;
                    151:     }
                    152:   if (pos + len > dd->len)
                    153:     return 0;
                    154:   memcpy(buf, dd->data + pos, len);
                    155:   return 1;
                    156: }
                    157: 
                    158: static int
                    159: dump_write(struct pci_dev *d UNUSED, int pos UNUSED, byte *buf UNUSED, int len UNUSED)
                    160: {
                    161:   d->access->error("Writing to dump files is not supported.");
                    162:   return 0;
                    163: }
                    164: 
                    165: static void
                    166: dump_cleanup_dev(struct pci_dev *d)
                    167: {
                    168:   if (d->aux)
                    169:     {
                    170:       pci_mfree(d->aux);
                    171:       d->aux = NULL;
                    172:     }
                    173: }
                    174: 
                    175: struct pci_methods pm_dump = {
                    176:   "dump",
                    177:   "Reading of register dumps (set the `dump.name' parameter)",
                    178:   dump_config,
                    179:   dump_detect,
                    180:   dump_init,
                    181:   dump_cleanup,
                    182:   dump_scan,
                    183:   pci_generic_fill_info,
                    184:   dump_read,
                    185:   dump_write,
                    186:   NULL,                                        /* read_vpd */
                    187:   NULL,                                        /* init_dev */
                    188:   dump_cleanup_dev
                    189: };

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>