Add support for decoding Buffer objects that contain PnP/ACPI resource
streams. Since the output is bulky, it's controlled by the '-r' option. Document this in the manpage, and clean up some awkward English a little.
This commit is contained in:
parent
fbeabbfad6
commit
add420aa72
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=88802
@ -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
|
||||
<URL:http://www.teleport.com/~acpi/>
|
||||
.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
|
||||
|
@ -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;
|
||||
|
@ -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_ */
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user