File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pciutils / lib / dump.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Fri Feb 17 15:18:43 2012 UTC (13 years, 1 month ago) by misho
Branches: pciutils, MAIN
CVS tags: v3_1_9, HEAD
pciutils

    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>