1 /* 2 * The PCI Library -- Reading of Bus Dumps 3 * 4 * Copyright (c) 1997--2003 Martin Mares <[email protected]> 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 static int 17 dump_detect(struct pci_access *a) 18 { 19 return !!a->method_params[PCI_ACCESS_DUMP]; 20 } 21 22 static void 23 dump_init(struct pci_access *a) 24 { 25 char *name = a->method_params[PCI_ACCESS_DUMP]; 26 FILE *f; 27 char buf[256]; 28 struct pci_dev *dev = NULL; 29 int len, bn, dn, fn, i, j; 30 31 if (!a) 32 a->error("dump: File name not given."); 33 if (!(f = fopen(name, "r"))) 34 a->error("dump: Cannot open %s: %s", name, strerror(errno)); 35 while (fgets(buf, sizeof(buf)-1, f)) 36 { 37 char *z = strchr(buf, '\n'); 38 if (!z) 39 a->error("dump: line too long or unterminated"); 40 *z-- = 0; 41 if (z >= buf && *z == '\r') 42 *z-- = 0; 43 len = z - buf + 1; 44 if (len >= 8 && buf[2] == ':' && buf[5] == '.' && buf[7] == ' ' && 45 sscanf(buf, "%x:%x.%d ", &bn, &dn, &fn) == 3) 46 { 47 dev = pci_get_dev(a, 0, bn, dn, fn); 48 dev->aux = pci_malloc(a, 256); 49 memset(dev->aux, 0xff, 256); 50 pci_link_dev(a, dev); 51 } 52 else if (!len) 53 dev = NULL; 54 else if (dev && len >= 51 && buf[2] == ':' && buf[3] == ' ' && 55 sscanf(buf, "%x: ", &i) == 1) 56 { 57 z = buf+3; 58 while (isspace(z[0]) && isxdigit(z[1]) && isxdigit(z[2])) 59 { 60 z++; 61 if (sscanf(z, "%x", &j) != 1 || i >= 256) 62 a->error("dump: Malformed line"); 63 ((byte *) dev->aux)[i++] = j; 64 z += 2; 65 } 66 } 67 } 68 } 69 70 static void 71 dump_cleanup(struct pci_access *a UNUSED) 72 { 73 } 74 75 static void 76 dump_scan(struct pci_access *a UNUSED) 77 { 78 } 79 80 static int 81 dump_read(struct pci_dev *d, int pos, byte *buf, int len) 82 { 83 if (!d->aux) 84 { 85 struct pci_dev *e = d->access->devices; 86 while (e && (e->bus != d->bus || e->dev != d->dev || e->func != d->func)) 87 e = e->next; 88 if (e) 89 d = e; 90 else 91 return 0; 92 } 93 memcpy(buf, (byte *) d->aux + pos, len); 94 return 1; 95 } 96 97 static int 98 dump_write(struct pci_dev *d UNUSED, int pos UNUSED, byte *buf UNUSED, int len UNUSED) 99 { 100 d->access->error("Writing to dump files is not supported."); 101 return 0; 102 } 103 104 static void 105 dump_cleanup_dev(struct pci_dev *d) 106 { 107 if (d->aux) 108 { 109 pci_mfree(d->aux); 110 d->aux = NULL; 111 } 112 } 113 114 struct pci_methods pm_dump = { 115 "dump", 116 NULL, /* config */ 117 dump_detect, 118 dump_init, 119 dump_cleanup, 120 dump_scan, 121 pci_generic_fill_info, 122 dump_read, 123 dump_write, 124 NULL, /* init_dev */ 125 dump_cleanup_dev 126 }; 127