1 /*
2 * mjs copyright
3 *
4 */
5
6 #include <sys/cdefs.h>
7 __FBSDID("$FreeBSD$");
8
9 /*
10 * "Plug and Play" functionality.
11 *
12 * We use the PnP enumerators to obtain identifiers for installed hardware,
13 * and the contents of a database to determine modules to be loaded to support
14 * such hardware.
15 */
16
17 #include <stand.h>
18 #include <string.h>
19 #include <bootstrap.h>
20
21 static struct pnpinfo_stql pnp_devices;
22 static int pnp_devices_initted = 0;
23
24 static void pnp_discard(void);
25
26 /*
27 * Perform complete enumeration sweep
28 */
29
30 COMMAND_SET(pnpscan, "pnpscan", "scan for PnP devices", pnp_scan);
31
32 static int
pnp_scan(int argc,char * argv[])33 pnp_scan(int argc, char *argv[])
34 {
35 struct pnpinfo *pi;
36 int hdlr;
37 int verbose;
38 int ch;
39
40 if (pnp_devices_initted == 0) {
41 STAILQ_INIT(&pnp_devices);
42 pnp_devices_initted = 1;
43 }
44
45 verbose = 0;
46 optind = 1;
47 optreset = 1;
48 while ((ch = getopt(argc, argv, "v")) != -1) {
49 switch(ch) {
50 case 'v':
51 verbose = 1;
52 break;
53 case '?':
54 default:
55 /* getopt has already reported an error */
56 return(CMD_OK);
57 }
58 }
59
60 /* forget anything we think we knew */
61 pnp_discard();
62
63 /* iterate over all of the handlers */
64 for (hdlr = 0; pnphandlers[hdlr] != NULL; hdlr++) {
65 if (verbose)
66 printf("Probing %s...\n", pnphandlers[hdlr]->pp_name);
67 pnphandlers[hdlr]->pp_enumerate();
68 }
69 if (verbose) {
70 pager_open();
71 if (pager_output("PNP scan summary:\n"))
72 goto out;
73 STAILQ_FOREACH(pi, &pnp_devices, pi_link) {
74 pager_output(STAILQ_FIRST(&pi->pi_ident)->id_ident); /* first ident should be canonical */
75 if (pi->pi_desc != NULL) {
76 pager_output(" : ");
77 pager_output(pi->pi_desc);
78 }
79 if (pager_output("\n"))
80 break;
81 }
82 out:
83 pager_close();
84 }
85 return(CMD_OK);
86 }
87
88 /*
89 * Throw away anything we think we know about PnP devices.
90 */
91 static void
pnp_discard(void)92 pnp_discard(void)
93 {
94 struct pnpinfo *pi;
95
96 while (STAILQ_FIRST(&pnp_devices) != NULL) {
97 pi = STAILQ_FIRST(&pnp_devices);
98 STAILQ_REMOVE_HEAD(&pnp_devices, pi_link);
99 pnp_freeinfo(pi);
100 }
101 }
102
103 /*
104 * Add a unique identifier to (pi)
105 */
106 void
pnp_addident(struct pnpinfo * pi,char * ident)107 pnp_addident(struct pnpinfo *pi, char *ident)
108 {
109 struct pnpident *id;
110
111 STAILQ_FOREACH(id, &pi->pi_ident, id_link)
112 if (!strcmp(id->id_ident, ident))
113 return; /* already have this one */
114
115 id = malloc(sizeof(struct pnpident));
116 id->id_ident = strdup(ident);
117 STAILQ_INSERT_TAIL(&pi->pi_ident, id, id_link);
118 }
119
120 /*
121 * Allocate a new pnpinfo struct
122 */
123 struct pnpinfo *
pnp_allocinfo(void)124 pnp_allocinfo(void)
125 {
126 struct pnpinfo *pi;
127
128 pi = malloc(sizeof(struct pnpinfo));
129 bzero(pi, sizeof(struct pnpinfo));
130 STAILQ_INIT(&pi->pi_ident);
131 return(pi);
132 }
133
134 /*
135 * Release storage held by a pnpinfo struct
136 */
137 void
pnp_freeinfo(struct pnpinfo * pi)138 pnp_freeinfo(struct pnpinfo *pi)
139 {
140 struct pnpident *id;
141
142 while (!STAILQ_EMPTY(&pi->pi_ident)) {
143 id = STAILQ_FIRST(&pi->pi_ident);
144 STAILQ_REMOVE_HEAD(&pi->pi_ident, id_link);
145 free(id->id_ident);
146 free(id);
147 }
148 if (pi->pi_desc)
149 free(pi->pi_desc);
150 if (pi->pi_module)
151 free(pi->pi_module);
152 if (pi->pi_argv)
153 free(pi->pi_argv);
154 free(pi);
155 }
156
157 /*
158 * Add a new pnpinfo struct to the list.
159 */
160 void
pnp_addinfo(struct pnpinfo * pi)161 pnp_addinfo(struct pnpinfo *pi)
162 {
163 STAILQ_INSERT_TAIL(&pnp_devices, pi, pi_link);
164 }
165
166
167 /*
168 * Format an EISA id as a string in standard ISA PnP format, AAAIIRR
169 * where 'AAA' is the EISA vendor ID, II is the product ID and RR the revision ID.
170 */
171 char *
pnp_eisaformat(uint8_t * data)172 pnp_eisaformat(uint8_t *data)
173 {
174 static char idbuf[8];
175 const char hextoascii[] = "0123456789abcdef";
176
177 idbuf[0] = '@' + ((data[0] & 0x7c) >> 2);
178 idbuf[1] = '@' + (((data[0] & 0x3) << 3) + ((data[1] & 0xe0) >> 5));
179 idbuf[2] = '@' + (data[1] & 0x1f);
180 idbuf[3] = hextoascii[(data[2] >> 4)];
181 idbuf[4] = hextoascii[(data[2] & 0xf)];
182 idbuf[5] = hextoascii[(data[3] >> 4)];
183 idbuf[6] = hextoascii[(data[3] & 0xf)];
184 idbuf[7] = 0;
185 return(idbuf);
186 }
187