2 * Copyright (c) 2000-2002 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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
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>
34 #include <sys/types.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
;
71 ACPI_PHYSICAL_ADDRESS addr
;
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
,
84 static int aml_simulate_regcontent_read(int regtype
,
85 ACPI_PHYSICAL_ADDRESS addr
,
87 static int aml_simulate_regcontent_write(int regtype
,
88 ACPI_PHYSICAL_ADDRESS addr
,
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
);
95 aml_simulation_init(void)
98 aml_simulation_initialized
= 1;
99 TAILQ_INIT(&RegionContentList
);
100 aml_simulation_regload("region.ini");
104 aml_simulate_regcontent_add(int regtype
, ACPI_PHYSICAL_ADDRESS addr
, UINT8 value
)
106 struct ACPIRegionContent
*rc
;
108 rc
= malloc(sizeof(struct ACPIRegionContent
));
110 return (-1); /* malloc fail */
112 rc
->regtype
= regtype
;
116 TAILQ_INSERT_TAIL(&RegionContentList
, rc
, links
);
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
) {
131 return (1); /* found */
136 return (aml_simulate_regcontent_add(regtype
, addr
, *valuep
));
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
) {
150 return (1); /* exists */
154 return (aml_simulate_regcontent_add(regtype
, addr
, *valuep
));
158 aml_simulate_prompt(char *msg
, ACPI_INTEGER def_val
)
168 printf("(default: 0x%x ", val
);
169 printf(" / %u) >>", val
);
172 bzero(buf
, sizeof buf
);
174 if (read(0, buf
, sizeof buf
) == 0) {
177 if (buf
[0] == '\n') {
178 break; /* use default value */
180 if (buf
[0] == '0' && buf
[1] == 'x') {
181 val
= strtoq(buf
, &ep
, 16);
183 val
= strtoq(buf
, &ep
, 10);
191 aml_simulation_regload(const char *dumpfile
)
193 char buf
[256], *np
, *ep
;
194 struct ACPIRegionContent rc
;
197 if (!aml_simulation_initialized
) {
201 if ((fp
= fopen(dumpfile
, "r")) == NULL
) {
205 while (fgets(buf
, sizeof buf
, fp
) != NULL
) {
207 /* reading region type */
208 rc
.regtype
= strtoq(np
, &ep
, 10);
214 /* reading address */
215 rc
.addr
= strtoq(np
, &ep
, 16);
222 rc
.value
= strtoq(np
, &ep
, 16);
226 aml_simulate_regcontent_write(rc
.regtype
, rc
.addr
, &rc
.value
);
233 aml_simulation_regdump(const char *dumpfile
)
235 struct ACPIRegionContent
*rc
;
238 if (!aml_simulation_initialized
) {
241 if ((fp
= fopen(dumpfile
, "w")) == NULL
) {
242 warn("%s", dumpfile
);
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
);
254 TAILQ_INIT(&RegionContentList
);
258 * Space handlers on virtual machine
262 aml_vm_space_handler(
265 ACPI_PHYSICAL_ADDRESS Address
,
272 ACPI_INTEGER value
, i
;
274 static char *space_names
[] = {
275 "SYSTEM_MEMORY", "SYSTEM_IO", "PCI_CONFIG",
276 "EC", "SMBUS", "CMOS", "PCI_BAR_TARGET"};
281 for (i
= 0; (i
* 8) < BitWidth
; i
++) {
282 state
= aml_simulate_regcontent_read(SpaceID
,
285 return (AE_NO_MEMORY
);
287 value
|= val
<< (i
* 8);
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
,
297 Address
, BitWidth
, Value
, 0));
305 sprintf(msg
, "[write(%s, %2d, 0x%x)]",
306 space_names
[SpaceID
], BitWidth
, Address
);
307 value
= aml_simulate_prompt(msg
, *Value
);
310 for (i
= 0; (i
* 8) < BitWidth
; i
++) {
312 state
= aml_simulate_regcontent_write(SpaceID
,
315 return (AE_NO_MEMORY
);
324 #define DECLARE_VM_SPACE_HANDLER(name, id); \
326 aml_vm_space_handler_##name ( \
328 ACPI_PHYSICAL_ADDRESS Address, \
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
355 load_dsdt(const char *dsdtfile
)
357 char filetmp
[PATH_MAX
];
358 u_int8_t
*code
, *amlptr
;
362 ACPI_TABLE_HEADER
*Table
;
364 fd
= open(dsdtfile
, O_RDONLY
, 0);
369 if (fstat(fd
, &sb
) == -1) {
373 code
= mmap(NULL
, (size_t)sb
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, (off_t
)0);
379 if ((error
= AcpiInitializeSubsystem()) != AE_OK
) {
380 err(1, "AcpiInitializeSubsystem returned %d", error
);
385 * make sure DSDT data contains table header or not.
387 if (strncmp((char *)code
, "DSDT", 4) == 0) {
388 strncpy(filetmp
, dsdtfile
, sizeof(filetmp
));
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
);
398 write(fd2
, &dummy_dsdt_table
, sizeof(ACPI_TABLE_HEADER
));
400 write(fd2
, code
, sb
.st_size
);
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
);
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
);
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
);
428 if ((error
= AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT
,
430 aml_vm_space_handler_ec
,
431 NULL
, NULL
)) != AE_OK
) {
432 fprintf(stderr
, "could not initialise EC handler: %d\n", error
);
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
);
442 if ((error
= AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT
,
444 aml_vm_space_handler_cmos
,
445 NULL
, NULL
)) != AE_OK
) {
446 fprintf(stderr
, "could not initialise CMOS handler: %d\n", error
);
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
);
457 AcpiGbl_GlobalLockPresent
= TRUE
;
459 error
= AcpiDbReadTableFromFile (filetmp
, &Table
);
460 if (ACPI_FAILURE(error
)) {
461 fprintf(stderr
, "AcpiDbReadTableFromFile failed: %s\n",
462 AcpiFormatException(error
));
465 AeBuildLocalTables(Table
);
466 if (ACPI_FAILURE(error
= AeInstallTables())) {
467 fprintf(stderr
, "AeInstallTables failed: %s\n",
468 AcpiFormatException(error
));
472 AcpiUtSetIntegerWidth (Table
->Revision
);
475 AcpiGbl_DebuggerConfiguration
= 0;
476 AcpiDbUserCommands(':', NULL
);
478 if (strcmp(dsdtfile
, filetmp
) != 0) {
486 usage(const char *progname
)
489 printf("usage: %s dsdt_file\n", progname
);
493 BOOLEAN AcpiGbl_IgnoreErrors
= FALSE
;
496 main(int argc
, char *argv
[])
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");