kernel - Update swapcache manual page
[dragonfly.git] / usr.sbin / acpi / acpidb / acpidb.c
blob67683bdcd377e179ebe8fb9e73ffd22c62290a61
1 /*-
2 * Copyright (c) 2000-2002 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
26 * $FreeBSD: src/usr.sbin/acpi/acpidb/acpidb.c,v 1.1 2003/08/07 16:51:50 njl Exp $
27 * $DragonFly: src/usr.sbin/acpi/acpidb/acpidb.c,v 1.2 2007/01/17 17:31:19 y0netan1 Exp $
30 #include <sys/param.h>
31 #include <sys/queue.h>
32 #include <sys/mman.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
36 #include <assert.h>
37 #include <ctype.h>
38 #include <err.h>
39 #include <fcntl.h>
40 #include <limits.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <unistd.h>
45 #include <acpi.h>
46 #include <acconfig.h>
47 #include <aclocal.h>
48 #include <acobject.h>
49 #include <acstruct.h>
50 #include <acnamesp.h>
51 #include <acglobal.h>
52 #include <acdebug.h>
55 * Dummy DSDT Table Header
58 ACPI_TABLE_HEADER dummy_dsdt_table = {
59 "DSDT", 123, 1, 123, "OEMID", "OEMTBLID", 1, "CRID", 1
63 * Region space I/O routines on virtual machine
66 int aml_debug_prompt = 1;
68 struct ACPIRegionContent {
69 TAILQ_ENTRY(ACPIRegionContent) links;
70 int regtype;
71 ACPI_PHYSICAL_ADDRESS addr;
72 UINT8 value;
75 TAILQ_HEAD(ACPIRegionContentList, ACPIRegionContent);
76 struct ACPIRegionContentList RegionContentList;
78 static int aml_simulation_initialized = 0;
80 static void aml_simulation_init(void);
81 static int aml_simulate_regcontent_add(int regtype,
82 ACPI_PHYSICAL_ADDRESS addr,
83 UINT8 value);
84 static int aml_simulate_regcontent_read(int regtype,
85 ACPI_PHYSICAL_ADDRESS addr,
86 UINT8 *valuep);
87 static int aml_simulate_regcontent_write(int regtype,
88 ACPI_PHYSICAL_ADDRESS addr,
89 UINT8 *valuep);
90 static ACPI_INTEGER aml_simulate_prompt(char *msg, ACPI_INTEGER def_val);
91 static void aml_simulation_regload(const char *dumpfile);
92 static void aml_simulation_regdump(const char *dumpfile);
94 static void
95 aml_simulation_init(void)
98 aml_simulation_initialized = 1;
99 TAILQ_INIT(&RegionContentList);
100 aml_simulation_regload("region.ini");
103 static int
104 aml_simulate_regcontent_add(int regtype, ACPI_PHYSICAL_ADDRESS addr, UINT8 value)
106 struct ACPIRegionContent *rc;
108 rc = malloc(sizeof(struct ACPIRegionContent));
109 if (rc == NULL) {
110 return (-1); /* malloc fail */
112 rc->regtype = regtype;
113 rc->addr = addr;
114 rc->value = value;
116 TAILQ_INSERT_TAIL(&RegionContentList, rc, links);
117 return (0);
120 static int
121 aml_simulate_regcontent_read(int regtype, ACPI_PHYSICAL_ADDRESS addr, UINT8 *valuep)
123 struct ACPIRegionContent *rc;
125 if (!aml_simulation_initialized) {
126 aml_simulation_init();
128 TAILQ_FOREACH(rc, &RegionContentList, links) {
129 if (rc->regtype == regtype && rc->addr == addr) {
130 *valuep = rc->value;
131 return (1); /* found */
135 *valuep = 0;
136 return (aml_simulate_regcontent_add(regtype, addr, *valuep));
139 static int
140 aml_simulate_regcontent_write(int regtype, ACPI_PHYSICAL_ADDRESS addr, UINT8 *valuep)
142 struct ACPIRegionContent *rc;
144 if (!aml_simulation_initialized) {
145 aml_simulation_init();
147 TAILQ_FOREACH(rc, &RegionContentList, links) {
148 if (rc->regtype == regtype && rc->addr == addr) {
149 rc->value = *valuep;
150 return (1); /* exists */
154 return (aml_simulate_regcontent_add(regtype, addr, *valuep));
157 static ACPI_INTEGER
158 aml_simulate_prompt(char *msg, ACPI_INTEGER def_val)
160 char buf[16], *ep;
161 ACPI_INTEGER val;
163 val = def_val;
164 printf("DEBUG");
165 if (msg != NULL) {
166 printf("%s", msg);
168 printf("(default: 0x%x ", val);
169 printf(" / %u) >>", val);
170 fflush(stdout);
172 bzero(buf, sizeof buf);
173 while (1) {
174 if (read(0, buf, sizeof buf) == 0) {
175 continue;
177 if (buf[0] == '\n') {
178 break; /* use default value */
180 if (buf[0] == '0' && buf[1] == 'x') {
181 val = strtoq(buf, &ep, 16);
182 } else {
183 val = strtoq(buf, &ep, 10);
185 break;
187 return (val);
190 static void
191 aml_simulation_regload(const char *dumpfile)
193 char buf[256], *np, *ep;
194 struct ACPIRegionContent rc;
195 FILE *fp;
197 if (!aml_simulation_initialized) {
198 return;
201 if ((fp = fopen(dumpfile, "r")) == NULL) {
202 return;
205 while (fgets(buf, sizeof buf, fp) != NULL) {
206 np = buf;
207 /* reading region type */
208 rc.regtype = strtoq(np, &ep, 10);
209 if (np == ep) {
210 continue;
212 np = ep;
214 /* reading address */
215 rc.addr = strtoq(np, &ep, 16);
216 if (np == ep) {
217 continue;
219 np = ep;
221 /* reading value */
222 rc.value = strtoq(np, &ep, 16);
223 if (np == ep) {
224 continue;
226 aml_simulate_regcontent_write(rc.regtype, rc.addr, &rc.value);
229 fclose(fp);
232 static void
233 aml_simulation_regdump(const char *dumpfile)
235 struct ACPIRegionContent *rc;
236 FILE *fp;
238 if (!aml_simulation_initialized) {
239 return;
241 if ((fp = fopen(dumpfile, "w")) == NULL) {
242 warn("%s", dumpfile);
243 return;
245 while (!TAILQ_EMPTY(&RegionContentList)) {
246 rc = TAILQ_FIRST(&RegionContentList);
247 fprintf(fp, "%d 0x%x 0x%x\n",
248 rc->regtype, rc->addr, rc->value);
249 TAILQ_REMOVE(&RegionContentList, rc, links);
250 free(rc);
253 fclose(fp);
254 TAILQ_INIT(&RegionContentList);
258 * Space handlers on virtual machine
261 static ACPI_STATUS
262 aml_vm_space_handler(
263 UINT32 SpaceID,
264 UINT32 Function,
265 ACPI_PHYSICAL_ADDRESS Address,
266 UINT32 BitWidth,
267 ACPI_INTEGER *Value,
268 int Prompt)
270 int state;
271 UINT8 val;
272 ACPI_INTEGER value, i;
273 char msg[256];
274 static char *space_names[] = {
275 "SYSTEM_MEMORY", "SYSTEM_IO", "PCI_CONFIG",
276 "EC", "SMBUS", "CMOS", "PCI_BAR_TARGET"};
278 switch (Function) {
279 case ACPI_READ:
280 value = 0;
281 for (i = 0; (i * 8) < BitWidth; i++) {
282 state = aml_simulate_regcontent_read(SpaceID,
283 Address + i, &val);
284 if (state == -1) {
285 return (AE_NO_MEMORY);
287 value |= val << (i * 8);
289 *Value = value;
290 if (Prompt) {
291 sprintf(msg, "[read (%s, %2d, 0x%x)]",
292 space_names[SpaceID], BitWidth, Address);
293 *Value = aml_simulate_prompt(msg, value);
294 if (*Value != value) {
295 return(aml_vm_space_handler(SpaceID,
296 ACPI_WRITE,
297 Address, BitWidth, Value, 0));
300 break;
302 case ACPI_WRITE:
303 value = *Value;
304 if (Prompt) {
305 sprintf(msg, "[write(%s, %2d, 0x%x)]",
306 space_names[SpaceID], BitWidth, Address);
307 value = aml_simulate_prompt(msg, *Value);
309 *Value = value;
310 for (i = 0; (i * 8) < BitWidth; i++) {
311 val = value & 0xff;
312 state = aml_simulate_regcontent_write(SpaceID,
313 Address + i, &val);
314 if (state == -1) {
315 return (AE_NO_MEMORY);
317 value = value >> 8;
321 return (AE_OK);
324 #define DECLARE_VM_SPACE_HANDLER(name, id); \
325 static ACPI_STATUS \
326 aml_vm_space_handler_##name ( \
327 UINT32 Function, \
328 ACPI_PHYSICAL_ADDRESS Address, \
329 UINT32 BitWidth, \
330 ACPI_INTEGER *Value, \
331 void *HandlerContext, \
332 void *RegionContext) \
334 return (aml_vm_space_handler(id, Function, Address, \
335 BitWidth, Value, aml_debug_prompt)); \
338 DECLARE_VM_SPACE_HANDLER(system_memory, ACPI_ADR_SPACE_SYSTEM_MEMORY);
339 DECLARE_VM_SPACE_HANDLER(system_io, ACPI_ADR_SPACE_SYSTEM_IO);
340 DECLARE_VM_SPACE_HANDLER(pci_config, ACPI_ADR_SPACE_PCI_CONFIG);
341 DECLARE_VM_SPACE_HANDLER(ec, ACPI_ADR_SPACE_EC);
342 DECLARE_VM_SPACE_HANDLER(smbus, ACPI_ADR_SPACE_SMBUS);
343 DECLARE_VM_SPACE_HANDLER(cmos, ACPI_ADR_SPACE_CMOS);
344 DECLARE_VM_SPACE_HANDLER(pci_bar_target,ACPI_ADR_SPACE_PCI_BAR_TARGET);
346 static u_int8_t *mapped_rsdp;
347 #define ACPI_MAX_INIT_TABLES (16)
348 static ACPI_TABLE_DESC Tables[ACPI_MAX_INIT_TABLES];
351 * Load DSDT data file and invoke debugger
354 static int
355 load_dsdt(const char *dsdtfile)
357 char filetmp[PATH_MAX];
358 u_int8_t *code, *amlptr;
359 struct stat sb;
360 int fd, fd2;
361 int error;
362 ACPI_TABLE_HEADER *Table;
364 fd = open(dsdtfile, O_RDONLY, 0);
365 if (fd == -1) {
366 perror("open");
367 return (-1);
369 if (fstat(fd, &sb) == -1) {
370 perror("fstat");
371 return (-1);
373 code = mmap(NULL, (size_t)sb.st_size, PROT_READ, MAP_PRIVATE, fd, (off_t)0);
374 if (code == NULL) {
375 perror("mmap");
376 return (-1);
378 mapped_rsdp = code;
379 if ((error = AcpiInitializeSubsystem()) != AE_OK) {
380 err(1, "AcpiInitializeSubsystem returned %d", error);
381 return (-1);
385 * make sure DSDT data contains table header or not.
387 if (strncmp((char *)code, "DSDT", 4) == 0) {
388 strncpy(filetmp, dsdtfile, sizeof(filetmp));
389 } else {
390 mode_t mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
391 dummy_dsdt_table.Length = sizeof(ACPI_TABLE_HEADER) + sb.st_size;
392 snprintf(filetmp, sizeof(filetmp), "%s.tmp", dsdtfile);
393 fd2 = open(filetmp, O_WRONLY | O_CREAT | O_TRUNC, mode);
394 if (fd2 == -1) {
395 perror("open");
396 return (-1);
398 write(fd2, &dummy_dsdt_table, sizeof(ACPI_TABLE_HEADER));
400 write(fd2, code, sb.st_size);
401 close(fd2);
405 * Install the virtual machine version of address space handlers.
407 if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
408 ACPI_ADR_SPACE_SYSTEM_MEMORY,
409 aml_vm_space_handler_system_memory,
410 NULL, NULL)) != AE_OK) {
411 fprintf(stderr, "could not initialise SystemMemory handler: %d\n", error);
412 return (-1);
414 if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
415 ACPI_ADR_SPACE_SYSTEM_IO,
416 aml_vm_space_handler_system_io,
417 NULL, NULL)) != AE_OK) {
418 fprintf(stderr, "could not initialise SystemIO handler: %d\n", error);
419 return (-1);
421 if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
422 ACPI_ADR_SPACE_PCI_CONFIG,
423 aml_vm_space_handler_pci_config,
424 NULL, NULL)) != AE_OK) {
425 fprintf(stderr, "could not initialise PciConfig handler: %d\n", error);
426 return (-1);
428 if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
429 ACPI_ADR_SPACE_EC,
430 aml_vm_space_handler_ec,
431 NULL, NULL)) != AE_OK) {
432 fprintf(stderr, "could not initialise EC handler: %d\n", error);
433 return (-1);
435 if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
436 ACPI_ADR_SPACE_SMBUS,
437 aml_vm_space_handler_smbus,
438 NULL, NULL)) != AE_OK) {
439 fprintf(stderr, "could not initialise SMBUS handler: %d\n", error);
440 return (-1);
442 if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
443 ACPI_ADR_SPACE_CMOS,
444 aml_vm_space_handler_cmos,
445 NULL, NULL)) != AE_OK) {
446 fprintf(stderr, "could not initialise CMOS handler: %d\n", error);
447 return (-1);
449 if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
450 ACPI_ADR_SPACE_PCI_BAR_TARGET,
451 aml_vm_space_handler_pci_bar_target,
452 NULL, NULL)) != AE_OK) {
453 fprintf(stderr, "could not initialise PCI BAR TARGET handler: %d\n", error);
454 return (-1);
457 AcpiGbl_GlobalLockPresent = TRUE;
459 error = AcpiDbReadTableFromFile (filetmp, &Table);
460 if (ACPI_FAILURE(error)) {
461 fprintf(stderr, "AcpiDbReadTableFromFile failed: %s\n",
462 AcpiFormatException(error));
463 return (-1);
465 AeBuildLocalTables(Table);
466 if (ACPI_FAILURE(error = AeInstallTables())) {
467 fprintf(stderr, "AeInstallTables failed: %s\n",
468 AcpiFormatException(error));
469 return (-1);
472 AcpiUtSetIntegerWidth (Table->Revision);
474 AcpiDbInitialize();
475 AcpiGbl_DebuggerConfiguration = 0;
476 AcpiDbUserCommands(':', NULL);
478 if (strcmp(dsdtfile, filetmp) != 0) {
479 unlink(filetmp);
482 return (0);
485 static void
486 usage(const char *progname)
489 printf("usage: %s dsdt_file\n", progname);
490 exit(1);
493 BOOLEAN AcpiGbl_IgnoreErrors = FALSE;
496 main(int argc, char *argv[])
498 char *progname;
500 progname = argv[0];
502 if (argc == 1) {
503 usage(progname);
506 AcpiDbgLevel = ACPI_DEBUG_DEFAULT;
507 AcpiGbl_EnableInterpreterSlack = TRUE;
509 aml_simulation_regload("region.ini");
510 if (load_dsdt(argv[1]) == 0) {
511 aml_simulation_regdump("region.dmp");
514 return (0);