diff --git a/usr.sbin/acpi/acpidump/acpidump.8 b/usr.sbin/acpi/acpidump/acpidump.8 index f37ae54f1b39..2081f1d61dc7 100644 --- a/usr.sbin/acpi/acpidump/acpidump.8 +++ b/usr.sbin/acpi/acpidump/acpidump.8 @@ -37,9 +37,12 @@ .Nd dump ACPI tables .Sh SYNOPSIS .Nm +.Op Fl r .Nm +.Op Fl r .Op Fl o Ar dsdt_file_for_output .Nm +.Op Fl r .Op Fl f Ar dsdt_file_for_input .Sh DESCRIPTION The @@ -47,65 +50,68 @@ The command analyzes ACPI tables in physical memory and dumps them to standard output. In addition, .Nm -can disassemble some contents of the tables in AML +can disassemble AML (ACPI Machine Language) -and dump them in ASL +found in these tables and dump them as ASL (ACPI Source Language). .Pp -ACPI tables have an notably essential data block called DSDT -(Differentiated System Description Table), +ACPI tables have an essential data block (the DSDT, +Differentiated System Description Table), that includes information used on the kernel side such as -detail information about PnP hardware, procedures for controlling -a power management support and so on. +detailed information about PnP hardware, procedures for controlling +power management support and so on. .Nm -can extract a DSDT data block from physical memory and store it into +can extract the DSDT data block from physical memory and store it into a DSDT data file, and also can generate an output in ASL from a given DSDT data file. .Pp When .Nm -is invoked with no option, it will search ACPI tables from physical +is invoked without the +.Fl f +option, it will read ACPI tables from physical memory via a special file .Pa /dev/mem -and dump them. First, it searches Root System Description Pointer, -that has a signature +and dump them. First it searches for the RSDP +(Root System Description Pointer), +which has the signature .Qq RSD PTR\ \& , -and then gets RSDT +and then gets the RSDT (Root System Description Table), which includes a list of pointers to physical memory addresses for other tables. -RSDT itself and all other tables linked from RSDT are generically -called SDT -(System Description Table) -and their header has the common format which consists of items +The RSDT itself and all other tables linked from RSDT are generically +called SDTs +(System Description Tables) +and their header has a common format which consists of items such as Signature, Length, Revision, Checksum, OEMID, OEM Table ID, OEM Revision, Creator ID and Creator Revision. .Nm dumps contents of these SDTs. For further information about formats of each table, -see chapter 5: ACPI Software Programming Model, -.Dq Advanced Configuration and Power Interface Specification Revision 1.0b -from Intel/Microsoft/Toshiba. +see chapter 5: +.Dq ACPI Software Programming Model +from the ACPI specifications referenced below. .Pp There is always a pointer to a physical memory address in RSDT for FACP (Fixed ACPI Description Table). -FACP defines static system information about power management support +The FACP defines static system information about power management support (ACPI Hardware Register Implementation) such as interrupt mode (INT_MODEL), SCI interrupt number, SMI command port (SMI_CMD) and location of ACPI registers. -FACP also has a pointer to a physical memory address for DSDT, +The FACP also has a pointer to a physical memory address for DSDT, which includes information used on the kernel side such as PnP, power management support and so on. While the other tables are described in fixed format, -DSDT consists of AML data which compiled from sources -written in free formated ASL, description language for ACPI. +the DSDT consists of AML data which is compiled from sources +written in free formated ASL, which is the description language for ACPI. When .Nm outputs DSDT, it disassembles the AML data and -translates them into ASL. +formats it as ASL. .Sh OPTIONS The following options are supported by .Nm : @@ -118,6 +124,11 @@ in addition to behavior with no option. Interprets AML data in DSDT from a file specified in .Ar dsdt_file_for_input and dumps them in ASL to standard output. +.It Fl r +Additionally outputs commented ResourceTemplate() macros for Buffer +objects that contain valid resource streams. +These macros are defined in the ACPI 2.0 specification section +16.2.4. .It Fl h Displays usage and exit. .El @@ -148,7 +159,7 @@ specified by a pointer in FACP. Intel Microsoft Toshiba -Revision 1.0b +Revision 1.0b, 2.0 .Ed .Sh AUTHORS @@ -161,8 +172,9 @@ Some contributions made by .An Takayasu IWANASHI Aq takayasu@wendy.a.perfect-liberty.or.jp , .An Yoshihiko SARUMARU Aq mistral@imasy.or.jp , .An Hiroki Sato Aq hrs@FreeBSD.org , +.An Michael Lucas Aq mwlucas@blackhelicopters.org and -.An Michael Lucas Aq mwlucas@blackhelicopters.org . +.An Michael Smith Aq msmith@freebsd.org . .Sh HISTORY The .Nm diff --git a/usr.sbin/acpi/acpidump/acpidump.c b/usr.sbin/acpi/acpidump/acpidump.c index c7ca5d271b96..a68756868976 100644 --- a/usr.sbin/acpi/acpidump/acpidump.c +++ b/usr.sbin/acpi/acpidump/acpidump.c @@ -70,8 +70,8 @@ static void usage(const char *progname) { - printf("usage:\t%s [-o dsdt_file_for_output]\n", progname); - printf("\t%s [-f dsdt_file_for_input]\n", progname); + printf("usage:\t%s [-r] [-o dsdt_file_for_output]\n", progname); + printf("\t%s [-r] [-f dsdt_file_for_input]\n", progname); printf("\t%s [-h]\n", progname); exit(1); } @@ -82,7 +82,7 @@ main(int argc, char *argv[]) char c, *progname; progname = argv[0]; - while ((c = getopt(argc, argv, "f:o:h")) != -1) { + while ((c = getopt(argc, argv, "f:o:hr")) != -1) { switch (c) { case 'f': asl_dump_from_file(optarg); @@ -93,6 +93,9 @@ main(int argc, char *argv[]) case 'h': usage(progname); break; + case 'r': + rflag++; + break; default: argc -= optind; argv += optind; diff --git a/usr.sbin/acpi/acpidump/acpidump.h b/usr.sbin/acpi/acpidump/acpidump.h index 29905ed6d7b2..dd27f89ca74f 100644 --- a/usr.sbin/acpi/acpidump/acpidump.h +++ b/usr.sbin/acpi/acpidump/acpidump.h @@ -176,5 +176,6 @@ void acpi_load_dsdt(char *, u_int8_t **, u_int8_t **); void acpi_dump_dsdt(u_int8_t *, u_int8_t *); extern char *aml_dumpfile; extern struct ACPIsdt dsdt_header; +extern int rflag; #endif /* !_ACPIDUMP_H_ */ diff --git a/usr.sbin/acpi/acpidump/asl_dump.c b/usr.sbin/acpi/acpidump/asl_dump.c index 25f6777aed71..123fd5d3581f 100644 --- a/usr.sbin/acpi/acpidump/asl_dump.c +++ b/usr.sbin/acpi/acpidump/asl_dump.c @@ -39,6 +39,7 @@ #include "aml/aml_env.h" struct aml_environ asl_env; +int rflag; static u_int32_t asl_dump_pkglength(u_int8_t **dpp) @@ -228,6 +229,364 @@ asl_dump_defscope(u_int8_t **dpp, int indent) *dpp = dp; } +static void +asl_dump_resourcebuffer(u_int8_t *dp, u_int8_t *end, int indent) +{ + u_int8_t *p; + int print, len, name, indep, i, ofs; + + print = 0; + indep = 0; +restart: + if (print) { + printf("\n"); + print_indent(indent); + printf("/* ResourceTemplate() {\n"); + } + for (p = dp; p < end; ) { + ofs = p - dp; + if (*p & 0x80) { /* large resource */ + if ((end - p) < 3) { + return; + } + name = *p; + len = ((int)*(p + 2) << 8) + *(p + 1); + p += 3; + } else { /* small resource */ + name = (*p >> 3) & 0x0f; + len = *p & 0x7; + p++; + } + if (name == 0xf) { /* end tag */ + if (print == 0) { + print = 1; + goto restart; + } else { + print_indent(indent); + printf("} */\n"); + print_indent(indent); + break; + } + } + + if (print) { + print_indent(indent); + switch (name) { + case 0x06: + if (indep) { + printf(" }\n"); + print_indent(indent); + } + printf(" StartDependentFn("); + if (len == 1) + printf("%d, %d", + *p & 0x3, + (*p >> 2) & 0x3); + printf(") {\n"); + indep = 1; + continue; + case 0x07: + if (indep) + printf(" }\n"); + print_indent(indent); + printf(" EndDependentFn() {}\n"); + indep = 0; + continue; + } + + printf("%s 0x%-04.4x ", indep ? " " : "", ofs); + switch (name) { + case 0x04: /* IRQ() { } */ + { + int i, first; + + printf("IRQ("); + if (len == 3) { + printf("%s, Active%s, %s", + *(p + 2) & 0x01 ? "Edge" : "Level", + *(p + 2) & 0x08 ? "Low" : "High", + *(p + 2) & 0x10 ? "Shared" : + "Exclusive"); + } + printf(")"); + first = 1; + for (i = 0; i < 16; i++) { + if (*(p + (i / 8)) & (1 << (i % 8))) { + if (first) { + printf(" {"); + first = 0; + } else { + printf(", "); + } + printf("%d", i); + } + } + if (!first) + printf("}"); + printf("\n"); + break; + } + + case 0x05: /* DMA() { } */ + { + int i, first; + + printf("DMA(%s, %sBusMaster, Transfer%s)", + (*(p + 1) & 0x60) == 0 ? "Compatibility" : + (*(p + 1) & 0x60) == 1 ? "TypeA" : + (*(p + 1) & 0x60) == 2 ? "TypeB" : "TypeF", + *(p + 1) & 0x04 ? "" : "Not", + (*(p + 1) & 0x03) == 0 ? "8" : + (*(p + 1) & 0x03) == 1 ? "8_16" : "16"); + first = 1; + for (i = 0; i < 8; i++) { + if (*p & (1 << i)) { + if (first) { + printf(" {"); + first = 0; + } else { + printf(", "); + } + printf("%d", i); + } + } + if (!first) + printf("}"); + printf("\n"); + break; + } + case 0x08: /* IO() */ + printf("IO(Decode%s, 0x%x, 0x%x, 0x%x, 0x%x)\n", + *p & 0x01 ? "16" : "10", + (int)*(u_int16_t *)(p + 1), + (int)*(u_int16_t *)(p + 3), + *(p + 5), + *(p + 6)); + break; + + case 0x09: /* FixedIO() */ + printf("FixedIO(0x%x, 0x%x)\n", + *p + ((int)*(p + 1) << 8), + *(p + 2)); + break; + + case 0x0e: /* VendorShort() { }*/ + case 0x84: /* VendorLong() { } */ + { + int i, first; + + printf("Vendor%s()", name == 0x0e ? "Short" : "Long"); + first = 0; + for (i = 0; i < len; i++) { + if (first) { + printf(" {"); + first = 0; + } else { + printf(", "); + } + printf("0x%02x", *(p + i)); + } + if (!first) + printf("}"); + printf("\n"); + break; + } + case 0x81: /* Memory24() */ + printf("Memory24(Read%s, 0x%06x, 0x%06x, 0x%x, 0x%x)\n", + *p & 0x01 ? "Write" : "Only", + (u_int32_t)*(u_int16_t *)(p + 1) << 8, + (u_int32_t)*(u_int16_t *)(p + 3) << 8, + (int)*(u_int16_t *)(p + 5), + (int)*(u_int16_t *)(p + 7)); + break; + + case 0x82: /* Register() */ + printf("Register(%s, %d, %d, 0x%016llx)\n", + *p == 0x00 ? "SystemMemory" : + *p == 0x01 ? "SystemIO" : + *p == 0x02 ? "PCIConfigSpace" : + *p == 0x03 ? "EmbeddedController" : + *p == 0x04 ? "SMBus" : + *p == 0x7f ? "FunctionalFixedHardware" : "Unknown", + *(p + 1), + *(p + 2), + *(u_int64_t *)(p + 3)); + break; + + case 0x85: /* Memory32() */ + printf("Memory32(Read%s, 0x%08x, 0x%08x, 0x%x, 0x%x)\n", + *p & 0x01 ? "Write" : "Only", + *(u_int32_t *)(p + 1), + *(u_int32_t *)(p + 5), + *(u_int32_t *)(p + 9), + *(u_int32_t *)(p + 13)); + break; + + case 0x86: /* Memory32Fixed() */ + printf("Memory32Fixed(Read%s, 0x%08x, 0x%x)\n", + *p & 0x01 ? "Write" : "Only", + *(u_int32_t *)(p + 1), + *(u_int32_t *)(p + 5)); + break; + + case 0x87: /* DWordMemory() / DWordIO() */ + case 0x88: /* WordMemory() / WordIO() */ + case 0x8a: /* QWordMemory() / QWordIO() */ + { + u_int64_t granularity, minimum, maximum, translation, length; + char *size, *source; + int index, slen; + + switch (name) { + case 0x87: + size = "D"; + granularity = *(u_int32_t *)(p + 3); + minimum = *(u_int32_t *)(p + 7); + maximum = *(u_int32_t *)(p + 11); + translation = *(u_int32_t *)(p + 15); + length = *(u_int32_t *)(p + 19); + index = *(p + 23); + source = p + 24; + slen = len - 24; + break; + case 0x88: + size = ""; + granularity = *(u_int16_t *)(p + 3); + minimum = *(u_int16_t *)(p + 5); + maximum = *(u_int16_t *)(p + 7); + translation = *(u_int16_t *)(p + 9); + length = *(u_int16_t *)(p + 11); + index = *(p + 13); + source = p + 14; + slen = len - 14; + break; + case 0x8a: + size = "Q"; + granularity = *(u_int64_t *)(p + 3); + minimum = *(u_int64_t *)(p + 11); + maximum = *(u_int64_t *)(p + 19); + translation = *(u_int64_t *)(p + 27); + length = *(u_int64_t *)(p + 35); + index = *(p + 43); + source = p + 44; + slen = len - 44; + break; + } + switch(*p) { + case 0: + printf("%sWordMemory(" + "Resource%s, " + "%sDecode, " + "Min%sFixed, " + "Max%sFixed, " + "%s, " + "Read%s, " + "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, " + "%d, '%.*s', " + "AddressRange%s, " + "Type%s)\n", + size, + *(p + 1) & 0x01 ? "Consumer" : "Producer", + *(p + 1) & 0x02 ? "Sub" : "Pos", + *(p + 1) & 0x04 ? "" : "Not", + *(p + 1) & 0x08 ? "" : "Not", + (*(p + 2) >> 1) == 0 ? "NonCacheable" : + (*(p + 2) >> 1) == 1 ? "Cacheable" : + (*(p + 2) >> 1) == 2 ? "WriteCombining" : + "Prefetchable", + *(p + 2) & 0x01 ? "Write" : "Only", + granularity, minimum, maximum, translation, length, + index, slen, source, + ((*(p + 2) >> 3) & 0x03) == 0 ? "Memory" : + ((*(p + 2) >> 3) & 0x03) == 1 ? "Reserved" : + ((*(p + 2) >> 3) & 0x03) == 2 ? "ACPI" : "NVS", + *(p + 2) & 0x20 ? "Translation" : "Static"); + break; + case 1: + printf("%sWordIO(" + "Resource%s, " + "Min%sFixed, " + "Max%sFixed, " + "%sDecode, " + "%s, " + "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, " + "%d, '%.*s', " + "Type%s, " + "%sTranslation)\n", + size, + *(p + 1) & 0x01 ? "Consumer" : "Producer", + *(p + 1) & 0x04 ? "" : "Not", + *(p + 1) & 0x08 ? "" : "Not", + *(p + 1) & 0x02 ? "Sub" : "Pos", + (*(p + 2) & 0x03) == 0 ? "EntireRange" : + (*(p + 2) & 0x03) == 1 ? "NonISAOnlyRanges" : + (*(p + 2) & 0x03) == 2 ? "ISAOnlyRanges" : "EntireRange", + granularity, minimum, maximum, translation, length, + index, slen, source, + *(p + 2) & 0x10 ? "Translation" : "Static", + *(p + 2) & 0x20 ? "Sparse" : "Dense"); + break; + case 2: + printf("%sWordBus(" + "Resource%s, " + "%sDecode, " + "Min%sFixed, " + "Max%sFixed, " + "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, " + "%d, '%.*s')\n", + size, + *(p + 1) & 0x01 ? "Consumer" : "Producer", + *(p + 1) & 0x02 ? "Sub" : "Pos", + *(p + 1) & 0x04 ? "" : "Not", + *(p + 1) & 0x08 ? "" : "Not", + granularity, minimum, maximum, translation, length, + index, slen, source); + break; + default: + printf("%sWordUnknown()\n", size); + } + break; + } + case 0x89: /* Interrupt() { } */ + { + int i, first, pad, sl; + char *rp; + + pad = *(p + 1) * 4; + rp = p + 1 + pad; + sl = len - pad - 3; + printf("Interrupt(Resource%s, %s, Active%s, %s, %d, %.*s)", + *p & 0x01 ? "Producer" : "Consumer", + *p & 0x02 ? "Edge" : "Level", + *p & 0x04 ? "Low" : "High", + *p & 0x08 ? "Shared" : "Exclusive", + (int)*(p + 1 + pad), + sl, + rp); + first = 1; + for (i = 0; i < *(p + 1); i++) { + if (first) { + printf(" {"); + first = 0; + } else { + printf(", "); + } + printf("%u", *(u_int32_t *)(p + 2 + (i * 4))); + } + if (!first) + printf("}"); + printf("\n"); + break; + } + default: + printf("Unknown(0x%x, %d)\n", name, len); + break; + } + } + p += len; + } +} + static void asl_dump_defbuffer(u_int8_t **dpp, int indent) { @@ -242,12 +601,15 @@ asl_dump_defbuffer(u_int8_t **dpp, int indent) end = start + pkglength; printf("Buffer("); asl_dump_termobj(&dp, indent); + start = dp; printf(") {"); while (dp < end) { printf("0x%x", *dp++); if (dp < end) printf(", "); } + if (rflag) + asl_dump_resourcebuffer(start, end, indent); printf(" }"); *dpp = dp;