Annotation of embedaddon/pciutils/lib/dump.c, revision 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>