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>