1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include "superiotool.h"
25
26#if defined(__FreeBSD__)
27#include <fcntl.h>
28#include <unistd.h>
29#endif
30
31
32int dump = 0, verbose = 0, extra_dump = 0;
33
34
35int chip_found = 0;
36
37uint8_t regval(uint16_t port, uint8_t reg)
38{
39 OUTB(reg, port);
40 return INB(port + ((port == 0x3bd) ? 2 : 1));
41}
42
43void regwrite(uint16_t port, uint8_t reg, uint8_t val)
44{
45 OUTB(reg, port);
46 OUTB(val, port + 1);
47}
48
49void enter_conf_mode_winbond_fintek_ite_8787(uint16_t port)
50{
51 OUTB(0x87, port);
52 OUTB(0x87, port);
53}
54
55void exit_conf_mode_winbond_fintek_ite_8787(uint16_t port)
56{
57 OUTB(0xaa, port);
58 regwrite(port, 0x02, 0x02);
59}
60
61void enter_conf_mode_fintek_7777(uint16_t port)
62{
63 OUTB(0x77, port);
64 OUTB(0x77, port);
65}
66
67void exit_conf_mode_fintek_7777(uint16_t port)
68{
69 OUTB(0xaa, port);
70}
71
72int superio_unknown(const struct superio_registers reg_table[], uint16_t id)
73{
74 return !strncmp(get_superio_name(reg_table, id), "<unknown>", 9);
75}
76
77
78const char *get_superio_name(const struct superio_registers reg_table[],
79 uint16_t id)
80{
81 int i;
82
83 for (i = 0; ; i++) {
84 if (reg_table[i].superio_id == EOT)
85 break;
86
87 if ((uint16_t)reg_table[i].superio_id != id)
88 continue;
89
90 return reg_table[i].name;
91 }
92
93 return "<unknown>";
94}
95
96static void dump_regs(const struct superio_registers reg_table[],
97 int i, int j, uint16_t port, uint8_t ldn_sel)
98{
99 int k;
100 const int16_t *idx;
101
102 if (reg_table[i].ldn[j].ldn != NOLDN) {
103 printf("LDN 0x%02x", reg_table[i].ldn[j].ldn);
104 if (reg_table[i].ldn[j].name != NULL)
105 printf(" (%s)", reg_table[i].ldn[j].name);
106 regwrite(port, ldn_sel, reg_table[i].ldn[j].ldn);
107 } else {
108 if (reg_table[i].ldn[j].name == NULL)
109 printf("Register dump:");
110 else
111 printf("(%s)", reg_table[i].ldn[j].name);
112 }
113
114 idx = reg_table[i].ldn[j].idx;
115
116 printf("\nidx");
117 for (k = 0; idx[k] != EOT; k++) {
118 if (k && !(k % 8))
119 putchar(' ');
120 printf(" %02x", idx[k]);
121 }
122
123 printf("\nval");
124 for (k = 0; idx[k] != EOT; k++) {
125 if (k && !(k % 8))
126 putchar(' ');
127 printf(" %02x", regval(port, idx[k]));
128 }
129
130 printf("\ndef");
131 idx = reg_table[i].ldn[j].def;
132 for (k = 0; idx[k] != EOT; k++) {
133 if (k && !(k % 8))
134 putchar(' ');
135 if (idx[k] == NANA)
136 printf(" NA");
137 else if (idx[k] == RSVD)
138 printf(" RR");
139 else if (idx[k] == MISC)
140 printf(" MM");
141 else
142 printf(" %02x", idx[k]);
143 }
144 printf("\n");
145}
146
147void dump_superio(const char *vendor,
148 const struct superio_registers reg_table[],
149 uint16_t port, uint16_t id, uint8_t ldn_sel)
150{
151 int i, j, no_dump_available = 1;
152
153 if (!dump)
154 return;
155
156 for (i = 0; ; i++) {
157 if (reg_table[i].superio_id == EOT)
158 break;
159
160 if ((uint16_t)reg_table[i].superio_id != id)
161 continue;
162
163 for (j = 0; ; j++) {
164 if (reg_table[i].ldn[j].ldn == EOT)
165 break;
166 no_dump_available = 0;
167 dump_regs(reg_table, i, j, port, ldn_sel);
168 }
169
170 if (no_dump_available)
171 printf("No dump available for this Super I/O\n");
172 }
173}
174
175void dump_io(uint16_t iobase, uint16_t length)
176{
177 uint16_t i;
178
179 printf("Dumping %d I/O mapped registers at base 0x%04x:\n",
180 length, iobase);
181 for (i = 0; i < length; i++)
182 printf("%02x ", i);
183 printf("\n");
184 for (i = 0; i < length; i++)
185 printf("%02x ", INB(iobase + i));
186 printf("\n");
187}
188
189void probing_for(const char *vendor, const char *info, uint16_t port)
190{
191 if (!verbose)
192 return;
193
194
195 printf("Probing for %s Super I/O %sat 0x%x...\n", vendor, info, port);
196}
197
198
199void print_vendor_chips(const char *vendor,
200 const struct superio_registers reg_table[])
201{
202 int i;
203
204 for (i = 0; reg_table[i].superio_id != EOT; i++) {
205 printf("%s %s", vendor, reg_table[i].name);
206
207
208 if (reg_table[i].ldn[0].ldn != EOT)
209 printf(" (dump available)");
210
211 printf("\n");
212 }
213
214
215 if (i != 0)
216 printf("\n");
217}
218
219
220void print_list_of_supported_chips(void)
221{
222 int i;
223
224 printf("Supported Super I/O chips:\n\n");
225
226 for (i = 0; i < ARRAY_SIZE(vendor_print_functions); i++)
227 vendor_print_functions[i].print_list();
228
229 printf("See <http://coreboot.org/Superiotool#Supported_devices> "
230 "for more information.\n");
231}
232
233static void print_version(void)
234{
235 printf("superiotool r%s\n", SUPERIOTOOL_VERSION);
236}
237
238int main(int argc, char *argv[])
239{
240 int i, j, opt, option_index;
241#if defined(__FreeBSD__)
242 int io_fd;
243#endif
244
245 static const struct option long_options[] = {
246 {"dump", no_argument, NULL, 'd'},
247 {"extra-dump", no_argument, NULL, 'e'},
248 {"list-supported", no_argument, NULL, 'l'},
249 {"verbose", no_argument, NULL, 'V'},
250 {"version", no_argument, NULL, 'v'},
251 {"help", no_argument, NULL, 'h'},
252 {0, 0, 0, 0}
253 };
254
255 while ((opt = getopt_long(argc, argv, "delVvh",
256 long_options, &option_index)) != EOF) {
257 switch (opt) {
258 case 'd':
259 dump = 1;
260 break;
261 case 'e':
262 extra_dump = 1;
263 break;
264 case 'l':
265 print_list_of_supported_chips();
266 exit(0);
267 break;
268 case 'V':
269 verbose = 1;
270 break;
271 case 'v':
272 print_version();
273 exit(0);
274 break;
275 case 'h':
276 printf(USAGE);
277 printf(USAGE_INFO);
278 exit(0);
279 break;
280 default:
281
282 exit(1);
283 break;
284 }
285 }
286
287#if defined(__FreeBSD__)
288 if ((io_fd = open("/dev/io", O_RDWR)) < 0) {
289 perror("/dev/io");
290#else
291 if (iopl(3) < 0) {
292 perror("iopl");
293#endif
294 printf("Superiotool must be run as root.\n");
295 exit(1);
296 }
297
298 print_version();
299
300#ifdef PCI_SUPPORT
301
302 pacc = pci_alloc();
303 pci_init(pacc);
304 pci_scan_bus(pacc);
305#endif
306
307 for (i = 0; i < ARRAY_SIZE(superio_ports_table); i++) {
308 for (j = 0; superio_ports_table[i].ports[j] != EOT; j++)
309 superio_ports_table[i].probe_idregs(
310 superio_ports_table[i].ports[j]);
311 }
312
313 if (!chip_found)
314 printf("No Super I/O found\n");
315
316#if defined(__FreeBSD__)
317 close(io_fd);
318#endif
319 return 0;
320}
321