1 /*
2  *  Author:  Daniel De Graaf <dgdegra@tycho.nsa.gov>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License version 2,
6  *  as published by the Free Software Foundation.
7  */
8 
9 #include <stdlib.h>
10 #include <errno.h>
11 #include <stdio.h>
12 #include <xenctrl.h>
13 #include <fcntl.h>
14 #include <sys/mman.h>
15 #include <sys/stat.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <inttypes.h>
19 
20 /* Pulled from linux/include/linux/ioport.h */
21 #define IORESOURCE_TYPE_BITS    0x00001f00  /* Resource type */
22 #define IORESOURCE_IO       0x00000100
23 #define IORESOURCE_MEM      0x00000200
24 #define IORESOURCE_IRQ      0x00000400
25 #define IORESOURCE_DMA      0x00000800
26 #define IORESOURCE_BUS      0x00001000
27 
28 
usage(int argCnt,char * argv[])29 static void usage (int argCnt, char *argv[])
30 {
31 	fprintf(stderr, "Usage: %s SBDF label\n", argv[0]);
32 	exit(1);
33 }
34 
main(int argCnt,char * argv[])35 int main (int argCnt, char *argv[])
36 {
37 	int ret, err = 0;
38 	xc_interface *xch = 0;
39 	int seg, bus, dev, fn;
40 	uint32_t sbdf;
41 	uint64_t start, end, flags;
42 	char buf[1024];
43 	FILE *f;
44 
45 	if (argCnt != 3)
46 		usage(argCnt, argv);
47 
48 	xch = xc_interface_open(0,0,0);
49 	if ( !xch )
50 	{
51 		fprintf(stderr, "Unable to create interface to xenctrl: %s\n",
52 				strerror(errno));
53 		err = 1;
54 		goto done;
55 	}
56 
57 	sscanf(argv[1], "%x:%x:%x.%d", &seg, &bus, &dev, &fn);
58 	sbdf = (seg << 16) | (bus << 8) | (dev << 3) | fn;
59 
60 	snprintf(buf, sizeof(buf), "/sys/bus/pci/devices/%04x:%02x:%02x.%d/resource",
61 			seg, bus, dev, fn);
62 
63 	f = fopen(buf, "r");
64 	if (!f) {
65 		fprintf(stderr, "Unable to find device %s: %s\n", argv[1],
66 				strerror(errno));
67 		err = 1;
68 		goto done;
69 	}
70 
71 	ret = xc_flask_add_device(xch, sbdf, argv[2]);
72 	if (ret) {
73 		fprintf(stderr, "xc_flask_add_device: Unable to set context of PCI device %s (0x%x) to %s: %d\n",
74 			argv[1], sbdf, argv[2], ret);
75 		err = 2;
76 		goto done;
77 	}
78 
79 	while (fscanf(f, "0x%"SCNx64" 0x%"SCNx64" 0x%"SCNx64"\n", &start, &end, &flags) == 3) {
80 		if (flags & IORESOURCE_IO) {
81 			// printf("Port %"PRIx64"-%"PRIx64"\n", start, end);
82 			ret = xc_flask_add_ioport(xch, start, end, argv[2]);
83 			if (ret) {
84 				fprintf(stderr, "xc_flask_add_ioport %"PRIx64"-%"PRIx64" failed: %d\n",
85 						start, end, ret);
86 				err = 2;
87 			}
88 		} else if (flags & IORESOURCE_MEM) {
89 			start >>= 12;
90 			end >>= 12;
91 			// printf("IOMEM %"PRIx64"-%"PRIx64"\n", start, end);
92 			ret = xc_flask_add_iomem(xch, start, end, argv[2]);
93 			if (ret) {
94 				fprintf(stderr, "xc_flask_add_iomem %"PRIx64"-%"PRIx64" failed: %d\n",
95 						start, end, ret);
96 				err = 2;
97 			}
98 		}
99 	}
100 	fclose(f);
101 
102 	snprintf(buf, sizeof(buf), "/sys/bus/pci/devices/%04x:%02x:%02x.%d/irq",
103 			seg, bus, dev, fn);
104 	f = fopen(buf, "r");
105 	if (!f)
106 		goto done;
107 	if (fscanf(f, "%" SCNu64, &start) != 1)
108 		start = 0;
109 	if (start) {
110 		ret = xc_flask_add_pirq(xch, start, argv[2]);
111 		if (ret) {
112 			fprintf(stderr, "xc_flask_add_pirq %"PRIu64" failed: %d\n",
113 					start, ret);
114 			err = 2;
115 		}
116 	}
117 	fclose(f);
118 done:
119 	if ( xch )
120 		xc_interface_close(xch);
121 
122 	return err;
123 }
124