tools: add tool to decode AML files and build an ACPI namespace
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
TOOL_LIST := e64patch
|
||||
TOOL_LIST := e64patch amldecode
|
||||
|
||||
all:
|
||||
@for prog in $(TOOL_LIST); do \
|
||||
|
||||
8
tools/amldecode/Makefile
Normal file
8
tools/amldecode/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
TOOL_NAME := amldecode
|
||||
|
||||
include ../tool-config.mk
|
||||
|
||||
CFLAGS := -g
|
||||
LDFLAGS := -g
|
||||
|
||||
include ../tool-template.mk
|
||||
BIN
tools/amldecode/acpi-dsdt.aml
Normal file
BIN
tools/amldecode/acpi-dsdt.aml
Normal file
Binary file not shown.
598
tools/amldecode/acpi-dsdt.asl
Normal file
598
tools/amldecode/acpi-dsdt.asl
Normal file
@@ -0,0 +1,598 @@
|
||||
/*
|
||||
* Bochs/QEMU ACPI DSDT ASL definition
|
||||
*
|
||||
* Copyright (c) 2006 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
DefinitionBlock (
|
||||
"acpi-dsdt.aml", // Output Filename
|
||||
"DSDT", // Signature
|
||||
0x01, // DSDT Compliance Revision
|
||||
"BXPC", // OEMID
|
||||
"BXDSDT", // TABLE ID
|
||||
0x1 // OEM Revision
|
||||
)
|
||||
{
|
||||
Scope (\)
|
||||
{
|
||||
/* Debug Output */
|
||||
OperationRegion (DBG, SystemIO, 0xb044, 0x04)
|
||||
Field (DBG, DWordAcc, NoLock, Preserve)
|
||||
{
|
||||
DBGL, 32,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* PCI Bus definition */
|
||||
Scope(\_SB) {
|
||||
Device(PCI0) {
|
||||
Name (_HID, EisaId ("PNP0A03"))
|
||||
Name (_ADR, 0x00)
|
||||
Name (_UID, 1)
|
||||
Name(_PRT, Package() {
|
||||
/* PCI IRQ routing table, example from ACPI 2.0a specification,
|
||||
section 6.2.8.1 */
|
||||
/* Note: we provide the same info as the PCI routing
|
||||
table of the Bochs BIOS */
|
||||
#define prt_slot(nr, lnk0, lnk1, lnk2, lnk3) \
|
||||
Package() { nr##ffff, 0, lnk0, 0 }, \
|
||||
Package() { nr##ffff, 1, lnk1, 0 }, \
|
||||
Package() { nr##ffff, 2, lnk2, 0 }, \
|
||||
Package() { nr##ffff, 3, lnk3, 0 }
|
||||
|
||||
#define prt_slot0(nr) prt_slot(nr, LNKD, LNKA, LNKB, LNKC)
|
||||
#define prt_slot1(nr) prt_slot(nr, LNKA, LNKB, LNKC, LNKD)
|
||||
#define prt_slot2(nr) prt_slot(nr, LNKB, LNKC, LNKD, LNKA)
|
||||
#define prt_slot3(nr) prt_slot(nr, LNKC, LNKD, LNKA, LNKB)
|
||||
prt_slot0(0x0000),
|
||||
prt_slot1(0x0001),
|
||||
prt_slot2(0x0002),
|
||||
prt_slot3(0x0003),
|
||||
prt_slot0(0x0004),
|
||||
prt_slot1(0x0005),
|
||||
prt_slot2(0x0006),
|
||||
prt_slot3(0x0007),
|
||||
prt_slot0(0x0008),
|
||||
prt_slot1(0x0009),
|
||||
prt_slot2(0x000a),
|
||||
prt_slot3(0x000b),
|
||||
prt_slot0(0x000c),
|
||||
prt_slot1(0x000d),
|
||||
prt_slot2(0x000e),
|
||||
prt_slot3(0x000f),
|
||||
prt_slot0(0x0010),
|
||||
prt_slot1(0x0011),
|
||||
prt_slot2(0x0012),
|
||||
prt_slot3(0x0013),
|
||||
prt_slot0(0x0014),
|
||||
prt_slot1(0x0015),
|
||||
prt_slot2(0x0016),
|
||||
prt_slot3(0x0017),
|
||||
prt_slot0(0x0018),
|
||||
prt_slot1(0x0019),
|
||||
prt_slot2(0x001a),
|
||||
prt_slot3(0x001b),
|
||||
prt_slot0(0x001c),
|
||||
prt_slot1(0x001d),
|
||||
prt_slot2(0x001e),
|
||||
prt_slot3(0x001f),
|
||||
})
|
||||
|
||||
Name (_CRS, ResourceTemplate ()
|
||||
{
|
||||
WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
|
||||
0x0000, // Address Space Granularity
|
||||
0x0000, // Address Range Minimum
|
||||
0x00FF, // Address Range Maximum
|
||||
0x0000, // Address Translation Offset
|
||||
0x0100, // Address Length
|
||||
,, )
|
||||
IO (Decode16,
|
||||
0x0CF8, // Address Range Minimum
|
||||
0x0CF8, // Address Range Maximum
|
||||
0x01, // Address Alignment
|
||||
0x08, // Address Length
|
||||
)
|
||||
WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
|
||||
0x0000, // Address Space Granularity
|
||||
0x0000, // Address Range Minimum
|
||||
0x0CF7, // Address Range Maximum
|
||||
0x0000, // Address Translation Offset
|
||||
0x0CF8, // Address Length
|
||||
,, , TypeStatic)
|
||||
WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
|
||||
0x0000, // Address Space Granularity
|
||||
0x0D00, // Address Range Minimum
|
||||
0xFFFF, // Address Range Maximum
|
||||
0x0000, // Address Translation Offset
|
||||
0xF300, // Address Length
|
||||
,, , TypeStatic)
|
||||
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
|
||||
0x00000000, // Address Space Granularity
|
||||
0x000A0000, // Address Range Minimum
|
||||
0x000BFFFF, // Address Range Maximum
|
||||
0x00000000, // Address Translation Offset
|
||||
0x00020000, // Address Length
|
||||
,, , AddressRangeMemory, TypeStatic)
|
||||
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
|
||||
0x00000000, // Address Space Granularity
|
||||
0xC0000000, // Address Range Minimum
|
||||
0xFEBFFFFF, // Address Range Maximum
|
||||
0x00000000, // Address Translation Offset
|
||||
0x3EC00000, // Address Length
|
||||
,, , AddressRangeMemory, TypeStatic)
|
||||
})
|
||||
}
|
||||
Device(HPET) {
|
||||
Name(_HID, EISAID("PNP0103"))
|
||||
Name(_UID, 0)
|
||||
Method (_STA, 0, NotSerialized) {
|
||||
Return(0x0F)
|
||||
}
|
||||
Name(_CRS, ResourceTemplate() {
|
||||
DWordMemory(
|
||||
ResourceConsumer, PosDecode, MinFixed, MaxFixed,
|
||||
NonCacheable, ReadWrite,
|
||||
0x00000000,
|
||||
0xFED00000,
|
||||
0xFED003FF,
|
||||
0x00000000,
|
||||
0x00000400 /* 1K memory: FED00000 - FED003FF */
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Scope(\_SB.PCI0) {
|
||||
Device (VGA) {
|
||||
Name (_ADR, 0x00020000)
|
||||
Method (_S1D, 0, NotSerialized)
|
||||
{
|
||||
Return (0x00)
|
||||
}
|
||||
Method (_S2D, 0, NotSerialized)
|
||||
{
|
||||
Return (0x00)
|
||||
}
|
||||
Method (_S3D, 0, NotSerialized)
|
||||
{
|
||||
Return (0x00)
|
||||
}
|
||||
}
|
||||
|
||||
/* PIIX3 ISA bridge */
|
||||
Device (ISA) {
|
||||
Name (_ADR, 0x00010000)
|
||||
|
||||
/* PIIX PCI to ISA irq remapping */
|
||||
OperationRegion (P40C, PCI_Config, 0x60, 0x04)
|
||||
|
||||
/* Real-time clock */
|
||||
Device (RTC)
|
||||
{
|
||||
Name (_HID, EisaId ("PNP0B00"))
|
||||
Name (_CRS, ResourceTemplate ()
|
||||
{
|
||||
IO (Decode16, 0x0070, 0x0070, 0x10, 0x02)
|
||||
IRQNoFlags () {8}
|
||||
IO (Decode16, 0x0072, 0x0072, 0x02, 0x06)
|
||||
})
|
||||
}
|
||||
|
||||
/* Keyboard seems to be important for WinXP install */
|
||||
Device (KBD)
|
||||
{
|
||||
Name (_HID, EisaId ("PNP0303"))
|
||||
Method (_STA, 0, NotSerialized)
|
||||
{
|
||||
Return (0x0f)
|
||||
}
|
||||
|
||||
Method (_CRS, 0, NotSerialized)
|
||||
{
|
||||
Name (TMP, ResourceTemplate ()
|
||||
{
|
||||
IO (Decode16,
|
||||
0x0060, // Address Range Minimum
|
||||
0x0060, // Address Range Maximum
|
||||
0x01, // Address Alignment
|
||||
0x01, // Address Length
|
||||
)
|
||||
IO (Decode16,
|
||||
0x0064, // Address Range Minimum
|
||||
0x0064, // Address Range Maximum
|
||||
0x01, // Address Alignment
|
||||
0x01, // Address Length
|
||||
)
|
||||
IRQNoFlags ()
|
||||
{1}
|
||||
})
|
||||
Return (TMP)
|
||||
}
|
||||
}
|
||||
|
||||
/* PS/2 mouse */
|
||||
Device (MOU)
|
||||
{
|
||||
Name (_HID, EisaId ("PNP0F13"))
|
||||
Method (_STA, 0, NotSerialized)
|
||||
{
|
||||
Return (0x0f)
|
||||
}
|
||||
|
||||
Method (_CRS, 0, NotSerialized)
|
||||
{
|
||||
Name (TMP, ResourceTemplate ()
|
||||
{
|
||||
IRQNoFlags () {12}
|
||||
})
|
||||
Return (TMP)
|
||||
}
|
||||
}
|
||||
|
||||
/* PS/2 floppy controller */
|
||||
Device (FDC0)
|
||||
{
|
||||
Name (_HID, EisaId ("PNP0700"))
|
||||
Method (_STA, 0, NotSerialized)
|
||||
{
|
||||
Return (0x0F)
|
||||
}
|
||||
Method (_CRS, 0, NotSerialized)
|
||||
{
|
||||
Name (BUF0, ResourceTemplate ()
|
||||
{
|
||||
IO (Decode16, 0x03F2, 0x03F2, 0x00, 0x04)
|
||||
IO (Decode16, 0x03F7, 0x03F7, 0x00, 0x01)
|
||||
IRQNoFlags () {6}
|
||||
DMA (Compatibility, NotBusMaster, Transfer8) {2}
|
||||
})
|
||||
Return (BUF0)
|
||||
}
|
||||
}
|
||||
|
||||
/* Parallel port */
|
||||
Device (LPT)
|
||||
{
|
||||
Name (_HID, EisaId ("PNP0400"))
|
||||
Method (_STA, 0, NotSerialized)
|
||||
{
|
||||
Store (\_SB.PCI0.PX13.DRSA, Local0)
|
||||
And (Local0, 0x80000000, Local0)
|
||||
If (LEqual (Local0, 0))
|
||||
{
|
||||
Return (0x00)
|
||||
}
|
||||
Else
|
||||
{
|
||||
Return (0x0F)
|
||||
}
|
||||
}
|
||||
Method (_CRS, 0, NotSerialized)
|
||||
{
|
||||
Name (BUF0, ResourceTemplate ()
|
||||
{
|
||||
IO (Decode16, 0x0378, 0x0378, 0x08, 0x08)
|
||||
IRQNoFlags () {7}
|
||||
})
|
||||
Return (BUF0)
|
||||
}
|
||||
}
|
||||
|
||||
/* Serial Ports */
|
||||
Device (COM1)
|
||||
{
|
||||
Name (_HID, EisaId ("PNP0501"))
|
||||
Name (_UID, 0x01)
|
||||
Method (_STA, 0, NotSerialized)
|
||||
{
|
||||
Store (\_SB.PCI0.PX13.DRSC, Local0)
|
||||
And (Local0, 0x08000000, Local0)
|
||||
If (LEqual (Local0, 0))
|
||||
{
|
||||
Return (0x00)
|
||||
}
|
||||
Else
|
||||
{
|
||||
Return (0x0F)
|
||||
}
|
||||
}
|
||||
Method (_CRS, 0, NotSerialized)
|
||||
{
|
||||
Name (BUF0, ResourceTemplate ()
|
||||
{
|
||||
IO (Decode16, 0x03F8, 0x03F8, 0x00, 0x08)
|
||||
IRQNoFlags () {4}
|
||||
})
|
||||
Return (BUF0)
|
||||
}
|
||||
}
|
||||
|
||||
Device (COM2)
|
||||
{
|
||||
Name (_HID, EisaId ("PNP0501"))
|
||||
Name (_UID, 0x02)
|
||||
Method (_STA, 0, NotSerialized)
|
||||
{
|
||||
Store (\_SB.PCI0.PX13.DRSC, Local0)
|
||||
And (Local0, 0x80000000, Local0)
|
||||
If (LEqual (Local0, 0))
|
||||
{
|
||||
Return (0x00)
|
||||
}
|
||||
Else
|
||||
{
|
||||
Return (0x0F)
|
||||
}
|
||||
}
|
||||
Method (_CRS, 0, NotSerialized)
|
||||
{
|
||||
Name (BUF0, ResourceTemplate ()
|
||||
{
|
||||
IO (Decode16, 0x02F8, 0x02F8, 0x00, 0x08)
|
||||
IRQNoFlags () {3}
|
||||
})
|
||||
Return (BUF0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* PIIX4 PM */
|
||||
Device (PX13) {
|
||||
Name (_ADR, 0x00010003)
|
||||
|
||||
OperationRegion (P13C, PCI_Config, 0x5c, 0x24)
|
||||
Field (P13C, DWordAcc, NoLock, Preserve)
|
||||
{
|
||||
DRSA, 32,
|
||||
DRSB, 32,
|
||||
DRSC, 32,
|
||||
DRSE, 32,
|
||||
DRSF, 32,
|
||||
DRSG, 32,
|
||||
DRSH, 32,
|
||||
DRSI, 32,
|
||||
DRSJ, 32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* PCI IRQs */
|
||||
Scope(\_SB) {
|
||||
Field (\_SB.PCI0.ISA.P40C, ByteAcc, NoLock, Preserve)
|
||||
{
|
||||
PRQ0, 8,
|
||||
PRQ1, 8,
|
||||
PRQ2, 8,
|
||||
PRQ3, 8
|
||||
}
|
||||
|
||||
Device(LNKA){
|
||||
Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
|
||||
Name(_UID, 1)
|
||||
Name(_PRS, ResourceTemplate(){
|
||||
IRQ (Level, ActiveLow, Shared)
|
||||
{3,4,5,6,7,9,10,11,12}
|
||||
})
|
||||
Method (_STA, 0, NotSerialized)
|
||||
{
|
||||
Store (0x0B, Local0)
|
||||
If (And (0x80, PRQ0, Local1))
|
||||
{
|
||||
Store (0x09, Local0)
|
||||
}
|
||||
Return (Local0)
|
||||
}
|
||||
Method (_DIS, 0, NotSerialized)
|
||||
{
|
||||
Or (PRQ0, 0x80, PRQ0)
|
||||
}
|
||||
Method (_CRS, 0, NotSerialized)
|
||||
{
|
||||
Name (PRR0, ResourceTemplate ()
|
||||
{
|
||||
IRQ (Level, ActiveLow, Shared)
|
||||
{1}
|
||||
})
|
||||
CreateWordField (PRR0, 0x01, TMP)
|
||||
Store (PRQ0, Local0)
|
||||
If (LLess (Local0, 0x80))
|
||||
{
|
||||
ShiftLeft (One, Local0, TMP)
|
||||
}
|
||||
Else
|
||||
{
|
||||
Store (Zero, TMP)
|
||||
}
|
||||
Return (PRR0)
|
||||
}
|
||||
Method (_SRS, 1, NotSerialized)
|
||||
{
|
||||
CreateWordField (Arg0, 0x01, TMP)
|
||||
FindSetRightBit (TMP, Local0)
|
||||
Decrement (Local0)
|
||||
Store (Local0, PRQ0)
|
||||
}
|
||||
}
|
||||
Device(LNKB){
|
||||
Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
|
||||
Name(_UID, 2)
|
||||
Name(_PRS, ResourceTemplate(){
|
||||
IRQ (Level, ActiveLow, Shared)
|
||||
{3,4,5,6,7,9,10,11,12}
|
||||
})
|
||||
Method (_STA, 0, NotSerialized)
|
||||
{
|
||||
Store (0x0B, Local0)
|
||||
If (And (0x80, PRQ1, Local1))
|
||||
{
|
||||
Store (0x09, Local0)
|
||||
}
|
||||
Return (Local0)
|
||||
}
|
||||
Method (_DIS, 0, NotSerialized)
|
||||
{
|
||||
Or (PRQ1, 0x80, PRQ1)
|
||||
}
|
||||
Method (_CRS, 0, NotSerialized)
|
||||
{
|
||||
Name (PRR0, ResourceTemplate ()
|
||||
{
|
||||
IRQ (Level, ActiveLow, Shared)
|
||||
{1}
|
||||
})
|
||||
CreateWordField (PRR0, 0x01, TMP)
|
||||
Store (PRQ1, Local0)
|
||||
If (LLess (Local0, 0x80))
|
||||
{
|
||||
ShiftLeft (One, Local0, TMP)
|
||||
}
|
||||
Else
|
||||
{
|
||||
Store (Zero, TMP)
|
||||
}
|
||||
Return (PRR0)
|
||||
}
|
||||
Method (_SRS, 1, NotSerialized)
|
||||
{
|
||||
CreateWordField (Arg0, 0x01, TMP)
|
||||
FindSetRightBit (TMP, Local0)
|
||||
Decrement (Local0)
|
||||
Store (Local0, PRQ1)
|
||||
}
|
||||
}
|
||||
Device(LNKC){
|
||||
Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
|
||||
Name(_UID, 3)
|
||||
Name(_PRS, ResourceTemplate(){
|
||||
IRQ (Level, ActiveLow, Shared)
|
||||
{3,4,5,6,7,9,10,11,12}
|
||||
})
|
||||
Method (_STA, 0, NotSerialized)
|
||||
{
|
||||
Store (0x0B, Local0)
|
||||
If (And (0x80, PRQ2, Local1))
|
||||
{
|
||||
Store (0x09, Local0)
|
||||
}
|
||||
Return (Local0)
|
||||
}
|
||||
Method (_DIS, 0, NotSerialized)
|
||||
{
|
||||
Or (PRQ2, 0x80, PRQ2)
|
||||
}
|
||||
Method (_CRS, 0, NotSerialized)
|
||||
{
|
||||
Name (PRR0, ResourceTemplate ()
|
||||
{
|
||||
IRQ (Level, ActiveLow, Shared)
|
||||
{1}
|
||||
})
|
||||
CreateWordField (PRR0, 0x01, TMP)
|
||||
Store (PRQ2, Local0)
|
||||
If (LLess (Local0, 0x80))
|
||||
{
|
||||
ShiftLeft (One, Local0, TMP)
|
||||
}
|
||||
Else
|
||||
{
|
||||
Store (Zero, TMP)
|
||||
}
|
||||
Return (PRR0)
|
||||
}
|
||||
Method (_SRS, 1, NotSerialized)
|
||||
{
|
||||
CreateWordField (Arg0, 0x01, TMP)
|
||||
FindSetRightBit (TMP, Local0)
|
||||
Decrement (Local0)
|
||||
Store (Local0, PRQ2)
|
||||
}
|
||||
}
|
||||
Device(LNKD){
|
||||
Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
|
||||
Name(_UID, 4)
|
||||
Name(_PRS, ResourceTemplate(){
|
||||
IRQ (Level, ActiveLow, Shared)
|
||||
{3,4,5,6,7,9,10,11,12}
|
||||
})
|
||||
Method (_STA, 0, NotSerialized)
|
||||
{
|
||||
Store (0x0B, Local0)
|
||||
If (And (0x80, PRQ3, Local1))
|
||||
{
|
||||
Store (0x09, Local0)
|
||||
}
|
||||
Return (Local0)
|
||||
}
|
||||
Method (_DIS, 0, NotSerialized)
|
||||
{
|
||||
Or (PRQ3, 0x80, PRQ3)
|
||||
}
|
||||
Method (_CRS, 0, NotSerialized)
|
||||
{
|
||||
Name (PRR0, ResourceTemplate ()
|
||||
{
|
||||
IRQ (Level, ActiveLow, Shared)
|
||||
{1}
|
||||
})
|
||||
CreateWordField (PRR0, 0x01, TMP)
|
||||
Store (PRQ3, Local0)
|
||||
If (LLess (Local0, 0x80))
|
||||
{
|
||||
ShiftLeft (One, Local0, TMP)
|
||||
}
|
||||
Else
|
||||
{
|
||||
Store (Zero, TMP)
|
||||
}
|
||||
Return (PRR0)
|
||||
}
|
||||
Method (_SRS, 1, NotSerialized)
|
||||
{
|
||||
CreateWordField (Arg0, 0x01, TMP)
|
||||
FindSetRightBit (TMP, Local0)
|
||||
Decrement (Local0)
|
||||
Store (Local0, PRQ3)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes:
|
||||
* must match piix4 emulation.
|
||||
*/
|
||||
Name (\_S3, Package (0x04)
|
||||
{
|
||||
0x01, /* PM1a_CNT.SLP_TYP */
|
||||
0x01, /* PM1b_CNT.SLP_TYP */
|
||||
Zero, /* reserved */
|
||||
Zero /* reserved */
|
||||
})
|
||||
Name (\_S4, Package (0x04)
|
||||
{
|
||||
Zero, /* PM1a_CNT.SLP_TYP */
|
||||
Zero, /* PM1b_CNT.SLP_TYP */
|
||||
Zero, /* reserved */
|
||||
Zero /* reserved */
|
||||
})
|
||||
Name (\_S5, Package (0x04)
|
||||
{
|
||||
Zero, /* PM1a_CNT.SLP_TYP */
|
||||
Zero, /* PM1b_CNT.SLP_TYP */
|
||||
Zero, /* reserved */
|
||||
Zero /* reserved */
|
||||
})
|
||||
}
|
||||
6
tools/amldecode/aml/constants.h
Normal file
6
tools/amldecode/aml/constants.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef AML_CONSTANTS_H_
|
||||
#define AML_CONSTANTS_H_
|
||||
|
||||
#define ACPI_OBJECT_NAME_MAX 5
|
||||
|
||||
#endif
|
||||
136
tools/amldecode/aml/object.c
Normal file
136
tools/amldecode/aml/object.c
Normal file
@@ -0,0 +1,136 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "object.h"
|
||||
|
||||
struct acpi_namespace *acpi_namespace_create(void)
|
||||
{
|
||||
struct acpi_namespace *ns = malloc(sizeof *ns);
|
||||
if (!ns) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(ns, 0x00, sizeof *ns);
|
||||
|
||||
ns->root = acpi_object_create("\\", ACPI_OBJECT_NAMESPACE);
|
||||
return ns;
|
||||
}
|
||||
|
||||
struct acpi_object *acpi_namespace_get_object(struct acpi_namespace *ns, const char *path)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct acpi_object *acpi_object_create(const char name[ACPI_OBJECT_NAME_MAX], enum acpi_object_type type)
|
||||
{
|
||||
struct acpi_object *object = malloc(sizeof *object);
|
||||
if (!object) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(object, 0x00, sizeof *object);
|
||||
|
||||
object->ref = 1;
|
||||
object->type = type;
|
||||
|
||||
if (name) {
|
||||
strncpy(object->name, name, sizeof object->name - 1);
|
||||
object->name[ACPI_OBJECT_NAME_MAX - 1] = '\0';
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
struct acpi_object *acpi_object_ref(struct acpi_object *object)
|
||||
{
|
||||
object->ref++;
|
||||
return object;
|
||||
}
|
||||
|
||||
void acpi_object_deref(struct acpi_object *object)
|
||||
{
|
||||
if (object->ref > 1) {
|
||||
object->ref--;
|
||||
return;
|
||||
}
|
||||
|
||||
object->ref = 0;
|
||||
free(object);
|
||||
}
|
||||
|
||||
void acpi_object_add_child(struct acpi_object *parent, struct acpi_object *child)
|
||||
{
|
||||
if (child->parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
child->parent = parent;
|
||||
if (!parent->first_child) {
|
||||
parent->first_child = acpi_object_ref(child);
|
||||
return;
|
||||
}
|
||||
|
||||
struct acpi_object *cur = parent->first_child;
|
||||
while (cur->next_sibling) {
|
||||
cur = cur->next_sibling;
|
||||
}
|
||||
|
||||
cur->next_sibling = acpi_object_ref(child);
|
||||
}
|
||||
|
||||
struct acpi_object *acpi_object_get_child(struct acpi_object *object, const char *name)
|
||||
{
|
||||
struct acpi_object *cur = object->first_child;
|
||||
while (cur) {
|
||||
if (!strcmp(cur->name, name)) {
|
||||
return acpi_object_ref(cur);
|
||||
}
|
||||
|
||||
cur = cur->next_sibling;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void acpi_object_print(struct acpi_object *object, int depth)
|
||||
{
|
||||
for (int i = 0; i < depth; i++) {
|
||||
fputs(" ", stdout);
|
||||
}
|
||||
|
||||
if (object->name[0] == 0) {
|
||||
printf("<unnamed>\n");
|
||||
} else {
|
||||
printf("%s [%s]\n", object->name, acpi_object_type_string(object->type));
|
||||
}
|
||||
|
||||
struct acpi_object *cur = object->first_child;
|
||||
while (cur) {
|
||||
acpi_object_print(cur, depth + 1);
|
||||
cur = cur->next_sibling;
|
||||
}
|
||||
}
|
||||
|
||||
#define OBJECT_TYPE_STRING(type) \
|
||||
case type: \
|
||||
return #type;
|
||||
|
||||
const char *acpi_object_type_string(enum acpi_object_type type)
|
||||
{
|
||||
switch (type) {
|
||||
OBJECT_TYPE_STRING(ACPI_OBJECT_NONE)
|
||||
OBJECT_TYPE_STRING(ACPI_OBJECT_VALUE)
|
||||
OBJECT_TYPE_STRING(ACPI_OBJECT_NAMESPACE)
|
||||
OBJECT_TYPE_STRING(ACPI_OBJECT_CPU)
|
||||
OBJECT_TYPE_STRING(ACPI_OBJECT_DEVICE)
|
||||
OBJECT_TYPE_STRING(ACPI_OBJECT_METHOD)
|
||||
OBJECT_TYPE_STRING(ACPI_OBJECT_POWER_RESOURCE)
|
||||
OBJECT_TYPE_STRING(ACPI_OBJECT_OPERATION_REGION)
|
||||
OBJECT_TYPE_STRING(ACPI_OBJECT_THERMAL_ZONE)
|
||||
OBJECT_TYPE_STRING(ACPI_OBJECT_FIELD)
|
||||
OBJECT_TYPE_STRING(ACPI_OBJECT_PACKAGE)
|
||||
OBJECT_TYPE_STRING(ACPI_OBJECT_BUFFER)
|
||||
default:
|
||||
return "<unknown>";
|
||||
}
|
||||
}
|
||||
52
tools/amldecode/aml/object.h
Normal file
52
tools/amldecode/aml/object.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef AML_OBJECT_H_
|
||||
#define AML_OBJECT_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include "constants.h"
|
||||
|
||||
enum acpi_object_type {
|
||||
ACPI_OBJECT_NONE = 0,
|
||||
ACPI_OBJECT_VALUE,
|
||||
ACPI_OBJECT_NAMESPACE,
|
||||
ACPI_OBJECT_CPU,
|
||||
ACPI_OBJECT_DEVICE,
|
||||
ACPI_OBJECT_METHOD,
|
||||
ACPI_OBJECT_POWER_RESOURCE,
|
||||
ACPI_OBJECT_OPERATION_REGION,
|
||||
ACPI_OBJECT_THERMAL_ZONE,
|
||||
ACPI_OBJECT_FIELD,
|
||||
ACPI_OBJECT_PACKAGE,
|
||||
ACPI_OBJECT_BUFFER,
|
||||
};
|
||||
|
||||
struct acpi_object {
|
||||
int ref;
|
||||
enum acpi_object_type type;
|
||||
union {
|
||||
char name[ACPI_OBJECT_NAME_MAX];
|
||||
char *publish_path;
|
||||
};
|
||||
|
||||
size_t scope_end;
|
||||
|
||||
struct acpi_object *parent;
|
||||
struct acpi_object *first_child, *next_sibling;
|
||||
};
|
||||
|
||||
struct acpi_namespace {
|
||||
struct acpi_object *root;
|
||||
};
|
||||
|
||||
extern struct acpi_namespace *acpi_namespace_create(void);
|
||||
extern struct acpi_object *acpi_namespace_get_object(struct acpi_namespace *ns, const char *path);
|
||||
|
||||
extern struct acpi_object *acpi_object_create(const char name[ACPI_OBJECT_NAME_MAX], enum acpi_object_type type);
|
||||
extern struct acpi_object *acpi_object_ref(struct acpi_object *object);
|
||||
extern void acpi_object_deref(struct acpi_object *object);
|
||||
extern void acpi_object_add_child(struct acpi_object *parent, struct acpi_object *child);
|
||||
extern struct acpi_object *acpi_object_get_child(struct acpi_object *object, const char *name);
|
||||
extern void acpi_object_print(struct acpi_object *object, int depth);
|
||||
|
||||
extern const char *acpi_object_type_string(enum acpi_object_type type);
|
||||
|
||||
#endif
|
||||
818
tools/amldecode/aml/opcode.c
Normal file
818
tools/amldecode/aml/opcode.c
Normal file
@@ -0,0 +1,818 @@
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "opcode.h"
|
||||
#include "value.h"
|
||||
#include "object.h"
|
||||
#include "parser.h"
|
||||
|
||||
#define BYTECODE(opcode, parser, name) \
|
||||
{ opcode, 0, parser, name }
|
||||
|
||||
#define EXT_BYTECODE(opcode, parser, name) \
|
||||
{ AML_EXT_OP, opcode, parser, name }
|
||||
|
||||
static int32_t read_pkg_length(struct aml_parser *parser)
|
||||
{
|
||||
int32_t p0 = aml_parser_advance(parser);
|
||||
if (p0 == PARSE_EOF) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
int32_t len = 0;
|
||||
int32_t tmp = 0;
|
||||
|
||||
int nbytes = (p0 & 0xC0) >> 6;
|
||||
switch (nbytes) {
|
||||
case 3:
|
||||
tmp = aml_parser_advance(parser);
|
||||
if (tmp == PARSE_EOF) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
len |= tmp << 20;
|
||||
case 2:
|
||||
tmp = aml_parser_advance(parser);
|
||||
if (tmp == PARSE_EOF) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
len |= tmp << 12;
|
||||
case 1:
|
||||
len |= p0 & 0x0F;
|
||||
tmp = aml_parser_advance(parser);
|
||||
if (tmp == PARSE_EOF) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
len |= tmp << 4;
|
||||
break;
|
||||
case 0:
|
||||
len = p0 & 0x3F;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static enum parse_status read_single_segment_name(struct aml_parser *parser, char name[ACPI_OBJECT_NAME_MAX])
|
||||
{
|
||||
name[0] = 0;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int c = aml_parser_advance(parser);
|
||||
if (c < 0) {
|
||||
return c;
|
||||
}
|
||||
|
||||
if (c == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == AML_ROOT_CHAR) {
|
||||
c = '\\';
|
||||
}
|
||||
|
||||
if (!isalnum(c) && c != '_' && c != '\\') {
|
||||
return PARSE_BADSTRING;
|
||||
}
|
||||
|
||||
name[i] = c;
|
||||
name[i + 1] = '\0';
|
||||
}
|
||||
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status read_name(struct aml_parser *parser, char **out)
|
||||
{
|
||||
int prefix = aml_parser_peek(parser);
|
||||
if (prefix < 0) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
int nsegments = 1;
|
||||
int root = 0;
|
||||
|
||||
if (prefix == AML_ROOT_CHAR) {
|
||||
root = 1;
|
||||
aml_parser_advance(parser);
|
||||
prefix = aml_parser_peek(parser);
|
||||
}
|
||||
|
||||
if (prefix == AML_DUAL_NAME_PREFIX) {
|
||||
aml_parser_advance(parser);
|
||||
nsegments = 2;
|
||||
} else if (prefix == AML_MULTI_NAME_PREFIX) {
|
||||
aml_parser_advance(parser);
|
||||
nsegments = aml_parser_advance(parser);
|
||||
}
|
||||
|
||||
/* each segment is 4 characters long, with a dot separator between each segment */
|
||||
size_t name_len = nsegments * 4 + (nsegments - 1) + 1;
|
||||
char *name = malloc(name_len + 1);
|
||||
if (!name) {
|
||||
return PARSE_NOMEM;
|
||||
}
|
||||
|
||||
size_t offset = 0;
|
||||
if (root) {
|
||||
name[offset++] = '\\';
|
||||
name[offset] = '\0';
|
||||
}
|
||||
|
||||
for (int seg = 0; seg < nsegments; seg++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int c = aml_parser_advance(parser);
|
||||
if (c < 0) {
|
||||
return c;
|
||||
}
|
||||
|
||||
if (c == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == AML_ROOT_CHAR) {
|
||||
c = '\\';
|
||||
}
|
||||
|
||||
if (!isalnum(c) && c != '_' && c != '\\') {
|
||||
return PARSE_BADSTRING;
|
||||
}
|
||||
|
||||
name[offset++] = c;
|
||||
name[offset] = '\0';
|
||||
}
|
||||
|
||||
if (seg < nsegments - 1) {
|
||||
name[offset++] = '.';
|
||||
name[offset] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
*out = name;
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status parse_zero(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
int opcode = aml_parser_advance(parser);
|
||||
out->type = AML_VALUE_UINT8;
|
||||
out->value.uint8 = 0;
|
||||
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status parse_one(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
int opcode = aml_parser_advance(parser);
|
||||
out->type = AML_VALUE_UINT8;
|
||||
out->value.uint8 = 1;
|
||||
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status parse_byte_prefix(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
int opcode = aml_parser_advance(parser);
|
||||
int a = aml_parser_advance(parser);
|
||||
if (a == PARSE_EOF) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
out->type = AML_VALUE_UINT8;
|
||||
out->value.uint8 = a;
|
||||
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status parse_word_prefix(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
int opcode = aml_parser_advance(parser);
|
||||
|
||||
int a = aml_parser_advance(parser);
|
||||
int b = aml_parser_advance(parser);
|
||||
|
||||
if (a == PARSE_EOF || b == PARSE_EOF) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
out->type = AML_VALUE_UINT16;
|
||||
out->value.uint16 = a | (b << 8);
|
||||
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status parse_dword_prefix(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
int opcode = aml_parser_advance(parser);
|
||||
|
||||
int a = aml_parser_advance(parser);
|
||||
int b = aml_parser_advance(parser);
|
||||
int c = aml_parser_advance(parser);
|
||||
int d = aml_parser_advance(parser);
|
||||
|
||||
if (a == PARSE_EOF || b == PARSE_EOF || c == PARSE_EOF || d == PARSE_EOF) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
out->type = AML_VALUE_UINT32;
|
||||
out->value.uint16 = a | (b << 8) | (c << 16) | (d << 24);
|
||||
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status parse_region(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status parse_qword_prefix(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
int opcode = aml_parser_advance(parser);
|
||||
|
||||
int64_t a = aml_parser_advance(parser);
|
||||
int64_t b = aml_parser_advance(parser);
|
||||
int64_t c = aml_parser_advance(parser);
|
||||
int64_t d = aml_parser_advance(parser);
|
||||
int64_t e = aml_parser_advance(parser);
|
||||
int64_t f = aml_parser_advance(parser);
|
||||
int64_t g = aml_parser_advance(parser);
|
||||
int64_t h = aml_parser_advance(parser);
|
||||
|
||||
if (a == PARSE_EOF || b == PARSE_EOF || c == PARSE_EOF || d == PARSE_EOF) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
if (e == PARSE_EOF || f == PARSE_EOF || g == PARSE_EOF || h == PARSE_EOF) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
out->type = AML_VALUE_UINT64;
|
||||
out->value.uint16 = a | (b << 8) | (c << 16) | (d << 24) | (e << 32) | (f << 40) | (g << 48) | (h << 56);
|
||||
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status parse_string_prefix(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
int opcode = aml_parser_advance(parser);
|
||||
|
||||
aml_parser_save_cursor(parser);
|
||||
unsigned int len = 0;
|
||||
while (1) {
|
||||
int c = aml_parser_advance(parser);
|
||||
if (c == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == PARSE_EOF) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
len++;
|
||||
}
|
||||
|
||||
aml_parser_load_cursor(parser);
|
||||
char *buf = malloc(len + 1);
|
||||
if (!buf) {
|
||||
return PARSE_NOMEM;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < len; i++) {
|
||||
int c = aml_parser_advance(parser);
|
||||
|
||||
if (c == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == PARSE_EOF) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
buf[i] = c;
|
||||
}
|
||||
|
||||
buf[len - 1] = '\0';
|
||||
|
||||
out->type = AML_VALUE_STRING;
|
||||
out->value.str = buf;
|
||||
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status parse_scope(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
int opcode = aml_parser_advance(parser);
|
||||
unsigned int scope_start = aml_parser_cursorpos(parser);
|
||||
int32_t scope_size = read_pkg_length(parser);
|
||||
if (scope_size < 0) {
|
||||
return scope_size;
|
||||
}
|
||||
|
||||
unsigned int scope_end = scope_start + scope_size;
|
||||
|
||||
char *scope_name;
|
||||
enum parse_status status = read_name(parser, &scope_name);
|
||||
if (status != PARSE_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
struct acpi_object *scope = aml_parser_resolve_path(parser, scope_name);
|
||||
|
||||
if (!scope) {
|
||||
scope = acpi_object_create(NULL, ACPI_OBJECT_NAMESPACE);
|
||||
scope->publish_path = scope_name;
|
||||
}
|
||||
|
||||
scope->scope_end = scope_end;
|
||||
|
||||
out->type = AML_VALUE_OBJECT;
|
||||
out->value.object = scope;
|
||||
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status parse_op_region(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
aml_parser_advance(parser);
|
||||
aml_parser_advance(parser);
|
||||
|
||||
char *name;
|
||||
enum parse_status status = read_name(parser, &name);
|
||||
|
||||
if (status != PARSE_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
int region_space = aml_parser_advance(parser);
|
||||
if (region_space < 0) {
|
||||
free(name);
|
||||
return region_space;
|
||||
}
|
||||
|
||||
struct aml_value region_offset;
|
||||
status = parse_opcode(parser, ®ion_offset);
|
||||
if (status != PARSE_OK) {
|
||||
free(name);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!aml_value_is_integer(®ion_offset)) {
|
||||
free(name);
|
||||
return PARSE_BADTYPE;
|
||||
}
|
||||
|
||||
struct aml_value region_len;
|
||||
status = parse_opcode(parser, ®ion_len);
|
||||
if (status != PARSE_OK) {
|
||||
free(name);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!aml_value_is_integer(®ion_len)) {
|
||||
free(name);
|
||||
return PARSE_BADTYPE;
|
||||
}
|
||||
|
||||
struct acpi_object *op_region = acpi_object_create(name, ACPI_OBJECT_OPERATION_REGION);
|
||||
op_region->publish_path = name;
|
||||
|
||||
out->type = AML_VALUE_OBJECT;
|
||||
out->value.object = op_region;
|
||||
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status parse_field(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
long start = aml_parser_cursorpos(parser);
|
||||
|
||||
aml_parser_advance(parser);
|
||||
aml_parser_advance(parser);
|
||||
|
||||
long len = read_pkg_length(parser);
|
||||
if (len < 0) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
char *name;
|
||||
enum parse_status status = read_name(parser, &name);
|
||||
if (status != PARSE_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
int flags = aml_parser_advance(parser);
|
||||
if (flags < 0) {
|
||||
free(name);
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
struct acpi_object *region = aml_parser_resolve_path(parser, name);
|
||||
free(name);
|
||||
|
||||
if (!region) {
|
||||
return PARSE_BADREF;
|
||||
}
|
||||
|
||||
long end = start + len;
|
||||
while (aml_parser_cursorpos(parser) < end) {
|
||||
char unit_name[ACPI_OBJECT_NAME_MAX];
|
||||
status = read_single_segment_name(parser, unit_name);
|
||||
if (status != PARSE_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
int bits = read_pkg_length(parser);
|
||||
if (bits < 0) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
struct acpi_object *field = acpi_object_create(unit_name, ACPI_OBJECT_FIELD);
|
||||
//field_unit->field_unit.size = bits / 8;
|
||||
|
||||
acpi_object_add_child(region, field);
|
||||
}
|
||||
|
||||
out->type = AML_VALUE_NONE;
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status parse_device(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
aml_parser_advance(parser);
|
||||
aml_parser_advance(parser);
|
||||
|
||||
long start = aml_parser_cursorpos(parser);
|
||||
|
||||
long len = read_pkg_length(parser);
|
||||
if (len < 0) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
char *name;
|
||||
enum parse_status status = read_name(parser, &name);
|
||||
if (status != PARSE_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
struct acpi_object *device = acpi_object_create(NULL, ACPI_OBJECT_DEVICE);
|
||||
device->publish_path = name;
|
||||
device->scope_end = start + len;
|
||||
|
||||
out->type = AML_VALUE_OBJECT;
|
||||
out->value.object = device;
|
||||
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status parse_name(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
aml_parser_advance(parser);
|
||||
|
||||
char *name;
|
||||
enum parse_status status = read_name(parser, &name);
|
||||
if (status != PARSE_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
struct aml_value named_value;
|
||||
status = parse_opcode(parser, &named_value);
|
||||
|
||||
if (status != PARSE_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
struct acpi_object *object = NULL;
|
||||
if (named_value.type == AML_VALUE_OBJECT) {
|
||||
object = named_value.value.object;
|
||||
} else {
|
||||
object = acpi_object_create(NULL, ACPI_OBJECT_VALUE);
|
||||
// TODO set value.
|
||||
}
|
||||
|
||||
object->publish_path = name;
|
||||
|
||||
out->type = AML_VALUE_OBJECT;
|
||||
out->value.object = object;
|
||||
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status parse_package(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
aml_parser_advance(parser);
|
||||
|
||||
long len = read_pkg_length(parser);
|
||||
if (len < 0) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
int nitems = aml_parser_advance(parser);
|
||||
if (nitems < 0) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
struct acpi_object *pkg = acpi_object_create(NULL, ACPI_OBJECT_PACKAGE);
|
||||
for (int i = 0; i < nitems; i++) {
|
||||
struct aml_value pkg_item;
|
||||
enum parse_status status = parse_opcode(parser, &pkg_item);
|
||||
if (status != PARSE_OK) {
|
||||
acpi_object_deref(pkg);
|
||||
return status;
|
||||
}
|
||||
|
||||
// TODO add value to package
|
||||
}
|
||||
|
||||
out->type = AML_VALUE_OBJECT;
|
||||
out->value.object = pkg;
|
||||
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status parse_name_chars(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
char *name;
|
||||
enum parse_status status = read_name(parser, &name);
|
||||
if (status != PARSE_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
out->type = AML_VALUE_NAME;
|
||||
out->value.name = name;
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status parse_buffer(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
aml_parser_advance(parser);
|
||||
long pkg_len = read_pkg_length(parser);
|
||||
if (pkg_len < 0) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
struct aml_value buffer_size;
|
||||
enum parse_status status = parse_opcode(parser, &buffer_size);
|
||||
if (status != PARSE_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!aml_value_is_integer(&buffer_size)) {
|
||||
return PARSE_BADTYPE;
|
||||
}
|
||||
|
||||
uint64_t nbytes = aml_value_get_integer(&buffer_size);
|
||||
|
||||
for (uint64_t i = 0; i < nbytes; i++) {
|
||||
int b = aml_parser_advance(parser);
|
||||
if (b < 0) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
}
|
||||
|
||||
struct acpi_object *buffer = acpi_object_create(NULL, ACPI_OBJECT_BUFFER);
|
||||
|
||||
out->type = AML_VALUE_OBJECT;
|
||||
out->value.object = buffer;
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
static enum parse_status parse_method(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
aml_parser_advance(parser);
|
||||
|
||||
long start = aml_parser_cursorpos(parser);
|
||||
|
||||
long pkg_len = read_pkg_length(parser);
|
||||
if (pkg_len < 0) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
char *name;
|
||||
enum parse_status status = read_name(parser, &name);
|
||||
if (status != PARSE_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
int flags = aml_parser_advance(parser);
|
||||
if (flags < 0) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
long end = start + pkg_len;
|
||||
while (aml_parser_cursorpos(parser) < end) {
|
||||
int b = aml_parser_advance(parser);
|
||||
if (b < 0) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
}
|
||||
|
||||
struct acpi_object *method = acpi_object_create(NULL, ACPI_OBJECT_METHOD);
|
||||
method->publish_path = name;
|
||||
|
||||
out->type = AML_VALUE_OBJECT;
|
||||
out->value.object = method;
|
||||
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
struct aml_byte_encoding byte_encoding[] = {
|
||||
BYTECODE(AML_ZERO_OP, parse_zero, "ZeroOp"),
|
||||
BYTECODE(AML_ONE_OP, parse_one, "OneOp"),
|
||||
BYTECODE(AML_ALIAS_OP, NULL, "AliasOp"),
|
||||
BYTECODE(AML_NAME_OP, parse_name, "NameOp"),
|
||||
BYTECODE(AML_BYTE_PREFIX, parse_byte_prefix, "BytePrefix"),
|
||||
BYTECODE(AML_WORD_PREFIX, parse_word_prefix, "WordPrefix"),
|
||||
BYTECODE(AML_DWORD_PREFIX, parse_dword_prefix, "DWordPrefix"),
|
||||
BYTECODE(AML_STRING_PREFIX, parse_string_prefix, "StringPrefix"),
|
||||
BYTECODE(AML_QWORD_PREFIX, parse_qword_prefix, "QWordPrefix"),
|
||||
BYTECODE(AML_SCOPE_OP, parse_scope, "ScopeOp"),
|
||||
BYTECODE(AML_BUFFER_OP, parse_buffer, "BufferOp"),
|
||||
BYTECODE(AML_PACKAGE_OP, parse_package, "PackageOp"),
|
||||
BYTECODE(AML_VAR_PACKAGE_OP, NULL, "VarPackageOp"),
|
||||
BYTECODE(AML_METHOD_OP, parse_method, "MethodOp"),
|
||||
BYTECODE(AML_DUAL_NAME_PREFIX, NULL, "DualNamePrefix"),
|
||||
BYTECODE(AML_MULTI_NAME_PREFIX, NULL, "MultiNamePrefix"),
|
||||
BYTECODE('0', parse_name_chars, "DigitChar"),
|
||||
BYTECODE('1', parse_name_chars, "DigitChar"),
|
||||
BYTECODE('2', parse_name_chars, "DigitChar"),
|
||||
BYTECODE('3', parse_name_chars, "DigitChar"),
|
||||
BYTECODE('4', parse_name_chars, "DigitChar"),
|
||||
BYTECODE('5', parse_name_chars, "DigitChar"),
|
||||
BYTECODE('6', parse_name_chars, "DigitChar"),
|
||||
BYTECODE('7', parse_name_chars, "DigitChar"),
|
||||
BYTECODE('8', parse_name_chars, "DigitChar"),
|
||||
BYTECODE('9', parse_name_chars, "DigitChar"),
|
||||
BYTECODE('A', parse_name_chars, "NameChar"),
|
||||
BYTECODE('B', parse_name_chars, "NameChar"),
|
||||
BYTECODE('C', parse_name_chars, "NameChar"),
|
||||
BYTECODE('D', parse_name_chars, "NameChar"),
|
||||
BYTECODE('E', parse_name_chars, "NameChar"),
|
||||
BYTECODE('F', parse_name_chars, "NameChar"),
|
||||
BYTECODE('G', parse_name_chars, "NameChar"),
|
||||
BYTECODE('H', parse_name_chars, "NameChar"),
|
||||
BYTECODE('I', parse_name_chars, "NameChar"),
|
||||
BYTECODE('J', parse_name_chars, "NameChar"),
|
||||
BYTECODE('K', parse_name_chars, "NameChar"),
|
||||
BYTECODE('L', parse_name_chars, "NameChar"),
|
||||
BYTECODE('M', parse_name_chars, "NameChar"),
|
||||
BYTECODE('N', parse_name_chars, "NameChar"),
|
||||
BYTECODE('O', parse_name_chars, "NameChar"),
|
||||
BYTECODE('P', parse_name_chars, "NameChar"),
|
||||
BYTECODE('Q', parse_name_chars, "NameChar"),
|
||||
BYTECODE('R', parse_name_chars, "NameChar"),
|
||||
BYTECODE('S', parse_name_chars, "NameChar"),
|
||||
BYTECODE('T', parse_name_chars, "NameChar"),
|
||||
BYTECODE('U', parse_name_chars, "NameChar"),
|
||||
BYTECODE('V', parse_name_chars, "NameChar"),
|
||||
BYTECODE('W', parse_name_chars, "NameChar"),
|
||||
BYTECODE('X', parse_name_chars, "NameChar"),
|
||||
BYTECODE('Y', parse_name_chars, "NameChar"),
|
||||
BYTECODE('Z', parse_name_chars, "NameChar"),
|
||||
EXT_BYTECODE(AML_EXT_MUTEX_OP, NULL, "MutexOp"),
|
||||
EXT_BYTECODE(AML_EXT_EVENT_OP, NULL, "EventOp"),
|
||||
EXT_BYTECODE(AML_EXT_COND_REF_OF_OP, NULL, "CondRefOfOp"),
|
||||
EXT_BYTECODE(AML_EXT_CREATE_FIELD_OP, NULL, "CreateFieldOp"),
|
||||
EXT_BYTECODE(AML_EXT_LOAD_TABLE_OP, NULL, "LoadTableOp"),
|
||||
EXT_BYTECODE(AML_EXT_LOAD_OP, NULL, "LoadOp"),
|
||||
EXT_BYTECODE(AML_EXT_STALL_OP, NULL, "StallOp"),
|
||||
EXT_BYTECODE(AML_EXT_SLEEP_OP, NULL, "SleepOp"),
|
||||
EXT_BYTECODE(AML_EXT_ACQUIRE_OP, NULL, "AcquireOp"),
|
||||
EXT_BYTECODE(AML_EXT_SIGNAL_OP, NULL, "SignalOp"),
|
||||
EXT_BYTECODE(AML_EXT_WAIT_OP, NULL, "WaitOp"),
|
||||
EXT_BYTECODE(AML_EXT_RESET_OP, NULL, "ResetOp"),
|
||||
EXT_BYTECODE(AML_EXT_RELEASE_OP, NULL, "ReleaseOp"),
|
||||
EXT_BYTECODE(AML_EXT_FROM_BCD_OP, NULL, "FromBCDOp"),
|
||||
EXT_BYTECODE(AML_EXT_TO_BCD_OP, NULL, "ToBCDOp"),
|
||||
EXT_BYTECODE(AML_EXT_UNLOAD_OP, NULL, "UnloadOp"),
|
||||
EXT_BYTECODE(AML_EXT_REVISION_OP, NULL, "RevisionOp"),
|
||||
EXT_BYTECODE(AML_EXT_DEBUG_OP, NULL, "DebugOp"),
|
||||
EXT_BYTECODE(AML_EXT_FATAL_OP, NULL, "FatalOp"),
|
||||
EXT_BYTECODE(AML_EXT_TIMER_OP, NULL, "TimerOp"),
|
||||
EXT_BYTECODE(AML_EXT_REGION_OP, parse_op_region, "OpRegionOp"),
|
||||
EXT_BYTECODE(AML_EXT_FIELD_OP, parse_field, "FieldOp"),
|
||||
EXT_BYTECODE(AML_EXT_DEVICE_OP, parse_device, "DeviceOp"),
|
||||
EXT_BYTECODE(AML_EXT_PROCESSOR_OP, NULL, "ProcessorOp"),
|
||||
EXT_BYTECODE(AML_EXT_POWER_RES_OP, NULL, "PowerResOp"),
|
||||
EXT_BYTECODE(AML_EXT_THERMAL_ZONE_OP, NULL, "ThermalZoneOp"),
|
||||
EXT_BYTECODE(AML_EXT_INDEX_FIELD_OP, NULL, "IndexFieldOp"),
|
||||
EXT_BYTECODE(AML_EXT_BANK_FIELD_OP, NULL, "BankFieldOp"),
|
||||
EXT_BYTECODE(AML_EXT_DATA_REGION_OP, NULL, "DataRegionOp"),
|
||||
BYTECODE(AML_ROOT_CHAR, NULL, "RootChar"),
|
||||
BYTECODE(AML_PARENT_PREFIX_CHAR, NULL, "ParentPrefixChar"),
|
||||
BYTECODE('_', NULL, "NameChar"),
|
||||
BYTECODE(AML_LOCAL0, NULL, "Local0Op"),
|
||||
BYTECODE(AML_LOCAL1, NULL, "Local1Op"),
|
||||
BYTECODE(AML_LOCAL2, NULL, "Local2Op"),
|
||||
BYTECODE(AML_LOCAL3, NULL, "Local3Op"),
|
||||
BYTECODE(AML_LOCAL4, NULL, "Local4Op"),
|
||||
BYTECODE(AML_LOCAL5, NULL, "Local5Op"),
|
||||
BYTECODE(AML_LOCAL6, NULL, "Local6Op"),
|
||||
BYTECODE(AML_LOCAL7, NULL, "Local7Op"),
|
||||
BYTECODE(AML_ARG0, NULL, "Arg0Op"),
|
||||
BYTECODE(AML_ARG1, NULL, "Arg1Op"),
|
||||
BYTECODE(AML_ARG2, NULL, "Arg2Op"),
|
||||
BYTECODE(AML_ARG3, NULL, "Arg3Op"),
|
||||
BYTECODE(AML_ARG4, NULL, "Arg4Op"),
|
||||
BYTECODE(AML_ARG5, NULL, "Arg5Op"),
|
||||
BYTECODE(AML_ARG6, NULL, "Arg6Op"),
|
||||
BYTECODE(AML_STORE_OP, NULL, "StoreOp"),
|
||||
BYTECODE(AML_REF_OF_OP, NULL, "RefOfOp"),
|
||||
BYTECODE(AML_ADD_OP, NULL, "AddOp"),
|
||||
BYTECODE(AML_CONCAT_OP, NULL, "ConcatOp"),
|
||||
BYTECODE(AML_SUBTRACT_OP, NULL, "SubtractOp"),
|
||||
BYTECODE(AML_INCREMENT_OP, NULL, "IncrementOp"),
|
||||
BYTECODE(AML_DECREMENT_OP, NULL, "DecrementOp"),
|
||||
BYTECODE(AML_MULTIPLY_OP, NULL, "MultiplyOp"),
|
||||
BYTECODE(AML_DIVIDE_OP, NULL, "DivideOp"),
|
||||
BYTECODE(AML_SHIFT_LEFT_OP, NULL, "ShiftLeftOp"),
|
||||
BYTECODE(AML_SHIFT_RIGHT_OP, NULL, "ShiftRightOp"),
|
||||
BYTECODE(AML_AND_OP, NULL, "AndOp"),
|
||||
BYTECODE(AML_NAND_OP, NULL, "NAndOp"),
|
||||
BYTECODE(AML_OR_OP, NULL, "OrOp"),
|
||||
BYTECODE(AML_NOR_OP, NULL, "NorOp"),
|
||||
BYTECODE(AML_XOR_OP, NULL, "XOrOp"),
|
||||
BYTECODE(AML_NOT_OP, NULL, "NotOp"),
|
||||
BYTECODE(AML_FIND_SET_LEFT_BIT_OP, NULL, "FindSetLeftBitOp"),
|
||||
BYTECODE(AML_FIND_SET_RIGHT_BIT_OP, NULL, "FindSetRightBitOp"),
|
||||
BYTECODE(AML_DEREF_OF_OP, NULL, "DerefOfOp"),
|
||||
BYTECODE(AML_CONCAT_RES_OP, NULL, "ConcatResOp"),
|
||||
BYTECODE(AML_MOD_OP, NULL, "ModOp"),
|
||||
BYTECODE(AML_NOTIFY_OP, NULL, "NotifyOp"),
|
||||
BYTECODE(AML_SIZE_OF_OP, NULL, "SizeOfOp"),
|
||||
BYTECODE(AML_INDEX_OP, NULL, "IndexOp"),
|
||||
BYTECODE(AML_MATCH_OP, NULL, "MatchOp"),
|
||||
BYTECODE(AML_CREATE_DWORD_FIELD_OP, NULL, "CreateDWordFieldOp"),
|
||||
BYTECODE(AML_CREATE_WORD_FIELD_OP, NULL, "CreateWordFieldOp"),
|
||||
BYTECODE(AML_CREATE_BYTE_FIELD_OP, NULL, "CreateByteFieldOp"),
|
||||
BYTECODE(AML_CREATE_BIT_FIELD_OP, NULL, "CreateBitFieldOp"),
|
||||
BYTECODE(AML_OBJECT_TYPE_OP, NULL, "ObjectTypeOp"),
|
||||
BYTECODE(AML_CREATE_QWORD_FIELD_OP, NULL, "CreateQWordFieldOp"),
|
||||
BYTECODE(AML_LAND_OP, NULL, "LAndOp"),
|
||||
BYTECODE(AML_LOR_OP, NULL, "LOrOp"),
|
||||
BYTECODE(AML_LNOT_OP, NULL, "LNotOp"),
|
||||
BYTECODE(AML_LEQUAL_OP, NULL, "LEqualOp"),
|
||||
BYTECODE(AML_LGREATER_OP, NULL, "LGreaterOp"),
|
||||
BYTECODE(AML_LLESS_OP, NULL, "LLessOp"),
|
||||
BYTECODE(AML_TO_BUFFER_OP, NULL, "ToBufferOp"),
|
||||
BYTECODE(AML_TO_DEC_STRING_OP, NULL, "ToDecimalStringOp"),
|
||||
BYTECODE(AML_TO_HEX_STRING_OP, NULL, "ToHexStringOp"),
|
||||
BYTECODE(AML_TO_INTEGER_OP, NULL, "ToIntegerOp"),
|
||||
BYTECODE(AML_TO_STRING_OP, NULL, "ToStringOp"),
|
||||
BYTECODE(AML_COPY_OBJECT_OP, NULL, "CopyObjectOp"),
|
||||
BYTECODE(AML_MID_OP, NULL, "MidOp"),
|
||||
BYTECODE(AML_CONTINUE_OP, NULL, "ContinueOp"),
|
||||
BYTECODE(AML_IF_OP, NULL, "IfOp"),
|
||||
BYTECODE(AML_ELSE_OP, NULL, "ElseOp"),
|
||||
BYTECODE(AML_WHILE_OP, NULL, "WhileOp"),
|
||||
BYTECODE(AML_NOOP_OP, NULL, "NoopOp"),
|
||||
BYTECODE(AML_RETURN_OP, NULL, "ReturnOp"),
|
||||
BYTECODE(AML_BREAK_OP, NULL, "BreakOp"),
|
||||
BYTECODE(AML_BREAK_POINT_OP, NULL, "BreakPointOp"),
|
||||
BYTECODE(AML_ONES_OP, NULL, "OnesOp"),
|
||||
};
|
||||
|
||||
static unsigned int nr_byte_encoding = sizeof byte_encoding / sizeof(struct aml_byte_encoding);
|
||||
|
||||
enum parse_status parse_opcode(struct aml_parser *parser, struct aml_value *out)
|
||||
{
|
||||
unsigned int offset = aml_parser_cursorpos(parser);
|
||||
int op0 = aml_parser_peek(parser);
|
||||
int op1 = 0;
|
||||
|
||||
if (op0 == PARSE_EOF) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
if (op0 == AML_EXT_OP) {
|
||||
op1 = aml_parser_peek_next(parser);
|
||||
if (op1 == PARSE_EOF) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
}
|
||||
|
||||
struct aml_byte_encoding *opcode = NULL;
|
||||
for (unsigned int i = 0; i < nr_byte_encoding; i++) {
|
||||
if (byte_encoding[i].opcode == op0 && byte_encoding[i].sub_opcode == op1) {
|
||||
opcode = &byte_encoding[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!opcode) {
|
||||
fprintf(stderr, "unrecognised opcode at 0x%04x: %02x:%02x\n", offset, op0, op1);
|
||||
return PARSE_UNKNOWNOP;
|
||||
}
|
||||
|
||||
if (!opcode->parser) {
|
||||
fprintf(stderr, "unimplemented opcode at 0x%04x: %02x:%02x (%s)\n", offset, op0, op1, opcode->name);
|
||||
return PARSE_UNKNOWNOP;
|
||||
}
|
||||
|
||||
return opcode->parser(parser, out);
|
||||
}
|
||||
190
tools/amldecode/aml/opcode.h
Normal file
190
tools/amldecode/aml/opcode.h
Normal file
@@ -0,0 +1,190 @@
|
||||
#ifndef AML_OPCODE_H_
|
||||
#define AML_OPCODE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "parser.h"
|
||||
|
||||
struct aml_parser;
|
||||
struct aml_value;
|
||||
|
||||
//
|
||||
// Primary OpCode
|
||||
//
|
||||
#define AML_ZERO_OP 0x00
|
||||
#define AML_ONE_OP 0x01
|
||||
#define AML_ALIAS_OP 0x06
|
||||
#define AML_NAME_OP 0x08
|
||||
#define AML_BYTE_PREFIX 0x0a
|
||||
#define AML_WORD_PREFIX 0x0b
|
||||
#define AML_DWORD_PREFIX 0x0c
|
||||
#define AML_STRING_PREFIX 0x0d
|
||||
#define AML_QWORD_PREFIX 0x0e
|
||||
#define AML_SCOPE_OP 0x10
|
||||
#define AML_BUFFER_OP 0x11
|
||||
#define AML_PACKAGE_OP 0x12
|
||||
#define AML_VAR_PACKAGE_OP 0x13
|
||||
#define AML_METHOD_OP 0x14
|
||||
#define AML_EXTERNAL_OP 0x15
|
||||
#define AML_DUAL_NAME_PREFIX 0x2e
|
||||
#define AML_MULTI_NAME_PREFIX 0x2f
|
||||
#define AML_NAME_CHAR_A 0x41
|
||||
#define AML_NAME_CHAR_B 0x42
|
||||
#define AML_NAME_CHAR_C 0x43
|
||||
#define AML_NAME_CHAR_D 0x44
|
||||
#define AML_NAME_CHAR_E 0x45
|
||||
#define AML_NAME_CHAR_F 0x46
|
||||
#define AML_NAME_CHAR_G 0x47
|
||||
#define AML_NAME_CHAR_H 0x48
|
||||
#define AML_NAME_CHAR_I 0x49
|
||||
#define AML_NAME_CHAR_J 0x4a
|
||||
#define AML_NAME_CHAR_K 0x4b
|
||||
#define AML_NAME_CHAR_L 0x4c
|
||||
#define AML_NAME_CHAR_M 0x4d
|
||||
#define AML_NAME_CHAR_N 0x4e
|
||||
#define AML_NAME_CHAR_O 0x4f
|
||||
#define AML_NAME_CHAR_P 0x50
|
||||
#define AML_NAME_CHAR_Q 0x51
|
||||
#define AML_NAME_CHAR_R 0x52
|
||||
#define AML_NAME_CHAR_S 0x53
|
||||
#define AML_NAME_CHAR_T 0x54
|
||||
#define AML_NAME_CHAR_U 0x55
|
||||
#define AML_NAME_CHAR_V 0x56
|
||||
#define AML_NAME_CHAR_W 0x57
|
||||
#define AML_NAME_CHAR_X 0x58
|
||||
#define AML_NAME_CHAR_Y 0x59
|
||||
#define AML_NAME_CHAR_Z 0x5a
|
||||
#define AML_ROOT_CHAR 0x5c
|
||||
#define AML_PARENT_PREFIX_CHAR 0x5e
|
||||
#define AML_NAME_CHAR__ 0x5f
|
||||
#define AML_LOCAL0 0x60
|
||||
#define AML_LOCAL1 0x61
|
||||
#define AML_LOCAL2 0x62
|
||||
#define AML_LOCAL3 0x63
|
||||
#define AML_LOCAL4 0x64
|
||||
#define AML_LOCAL5 0x65
|
||||
#define AML_LOCAL6 0x66
|
||||
#define AML_LOCAL7 0x67
|
||||
#define AML_ARG0 0x68
|
||||
#define AML_ARG1 0x69
|
||||
#define AML_ARG2 0x6a
|
||||
#define AML_ARG3 0x6b
|
||||
#define AML_ARG4 0x6c
|
||||
#define AML_ARG5 0x6d
|
||||
#define AML_ARG6 0x6e
|
||||
#define AML_STORE_OP 0x70
|
||||
#define AML_REF_OF_OP 0x71
|
||||
#define AML_ADD_OP 0x72
|
||||
#define AML_CONCAT_OP 0x73
|
||||
#define AML_SUBTRACT_OP 0x74
|
||||
#define AML_INCREMENT_OP 0x75
|
||||
#define AML_DECREMENT_OP 0x76
|
||||
#define AML_MULTIPLY_OP 0x77
|
||||
#define AML_DIVIDE_OP 0x78
|
||||
#define AML_SHIFT_LEFT_OP 0x79
|
||||
#define AML_SHIFT_RIGHT_OP 0x7a
|
||||
#define AML_AND_OP 0x7b
|
||||
#define AML_NAND_OP 0x7c
|
||||
#define AML_OR_OP 0x7d
|
||||
#define AML_NOR_OP 0x7e
|
||||
#define AML_XOR_OP 0x7f
|
||||
#define AML_NOT_OP 0x80
|
||||
#define AML_FIND_SET_LEFT_BIT_OP 0x81
|
||||
#define AML_FIND_SET_RIGHT_BIT_OP 0x82
|
||||
#define AML_DEREF_OF_OP 0x83
|
||||
#define AML_CONCAT_RES_OP 0x84
|
||||
#define AML_MOD_OP 0x85
|
||||
#define AML_NOTIFY_OP 0x86
|
||||
#define AML_SIZE_OF_OP 0x87
|
||||
#define AML_INDEX_OP 0x88
|
||||
#define AML_MATCH_OP 0x89
|
||||
#define AML_CREATE_DWORD_FIELD_OP 0x8a
|
||||
#define AML_CREATE_WORD_FIELD_OP 0x8b
|
||||
#define AML_CREATE_BYTE_FIELD_OP 0x8c
|
||||
#define AML_CREATE_BIT_FIELD_OP 0x8d
|
||||
#define AML_OBJECT_TYPE_OP 0x8e
|
||||
#define AML_CREATE_QWORD_FIELD_OP 0x8f
|
||||
#define AML_LAND_OP 0x90
|
||||
#define AML_LOR_OP 0x91
|
||||
#define AML_LNOT_OP 0x92
|
||||
#define AML_LEQUAL_OP 0x93
|
||||
#define AML_LGREATER_OP 0x94
|
||||
#define AML_LLESS_OP 0x95
|
||||
#define AML_TO_BUFFER_OP 0x96
|
||||
#define AML_TO_DEC_STRING_OP 0x97
|
||||
#define AML_TO_HEX_STRING_OP 0x98
|
||||
#define AML_TO_INTEGER_OP 0x99
|
||||
#define AML_TO_STRING_OP 0x9c
|
||||
#define AML_COPY_OBJECT_OP 0x9d
|
||||
#define AML_MID_OP 0x9e
|
||||
#define AML_CONTINUE_OP 0x9f
|
||||
#define AML_IF_OP 0xa0
|
||||
#define AML_ELSE_OP 0xa1
|
||||
#define AML_WHILE_OP 0xa2
|
||||
#define AML_NOOP_OP 0xa3
|
||||
#define AML_RETURN_OP 0xa4
|
||||
#define AML_BREAK_OP 0xa5
|
||||
#define AML_BREAK_POINT_OP 0xcc
|
||||
#define AML_ONES_OP 0xff
|
||||
|
||||
//
|
||||
// Extended OpCode
|
||||
//
|
||||
#define AML_EXT_OP 0x5b
|
||||
|
||||
#define AML_EXT_MUTEX_OP 0x01
|
||||
#define AML_EXT_EVENT_OP 0x02
|
||||
#define AML_EXT_COND_REF_OF_OP 0x12
|
||||
#define AML_EXT_CREATE_FIELD_OP 0x13
|
||||
#define AML_EXT_LOAD_TABLE_OP 0x1f
|
||||
#define AML_EXT_LOAD_OP 0x20
|
||||
#define AML_EXT_STALL_OP 0x21
|
||||
#define AML_EXT_SLEEP_OP 0x22
|
||||
#define AML_EXT_ACQUIRE_OP 0x23
|
||||
#define AML_EXT_SIGNAL_OP 0x24
|
||||
#define AML_EXT_WAIT_OP 0x25
|
||||
#define AML_EXT_RESET_OP 0x26
|
||||
#define AML_EXT_RELEASE_OP 0x27
|
||||
#define AML_EXT_FROM_BCD_OP 0x28
|
||||
#define AML_EXT_TO_BCD_OP 0x29
|
||||
#define AML_EXT_UNLOAD_OP 0x2a
|
||||
#define AML_EXT_REVISION_OP 0x30
|
||||
#define AML_EXT_DEBUG_OP 0x31
|
||||
#define AML_EXT_FATAL_OP 0x32
|
||||
#define AML_EXT_TIMER_OP 0x33
|
||||
#define AML_EXT_REGION_OP 0x80
|
||||
#define AML_EXT_FIELD_OP 0x81
|
||||
#define AML_EXT_DEVICE_OP 0x82
|
||||
#define AML_EXT_PROCESSOR_OP 0x83
|
||||
#define AML_EXT_POWER_RES_OP 0x84
|
||||
#define AML_EXT_THERMAL_ZONE_OP 0x85
|
||||
#define AML_EXT_INDEX_FIELD_OP 0x86
|
||||
#define AML_EXT_BANK_FIELD_OP 0x87
|
||||
#define AML_EXT_DATA_REGION_OP 0x88
|
||||
|
||||
//
|
||||
// FieldElement OpCode
|
||||
//
|
||||
#define AML_FIELD_RESERVED_OP 0x00
|
||||
#define AML_FIELD_ACCESS_OP 0x01
|
||||
#define AML_FIELD_CONNECTION_OP 0x02
|
||||
#define AML_FIELD_EXT_ACCESS_OP 0x03
|
||||
|
||||
//
|
||||
// AML Name segment definitions
|
||||
//
|
||||
#define AML_NAME_SEG_SIZE 4
|
||||
|
||||
typedef enum parse_status(*aml_bytecode_parser)(struct aml_parser *, struct aml_value *);
|
||||
|
||||
struct aml_byte_encoding {
|
||||
uint8_t opcode;
|
||||
uint8_t sub_opcode;
|
||||
|
||||
aml_bytecode_parser parser;
|
||||
|
||||
const char *name;
|
||||
};
|
||||
|
||||
extern enum parse_status parse_opcode(struct aml_parser *parser, struct aml_value *out);
|
||||
|
||||
#endif
|
||||
271
tools/amldecode/aml/parser.c
Normal file
271
tools/amldecode/aml/parser.c
Normal file
@@ -0,0 +1,271 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "parser.h"
|
||||
#include "opcode.h"
|
||||
#include "object.h"
|
||||
#include "value.h"
|
||||
|
||||
void aml_parser_init(struct aml_parser *parser, void *p, size_t len)
|
||||
{
|
||||
memset(parser, 0x0, sizeof *parser);
|
||||
|
||||
parser->start = parser->ptr = p;
|
||||
parser->end = parser->start + len;
|
||||
}
|
||||
|
||||
void aml_parser_set_namespace(struct aml_parser *parser, struct acpi_namespace *ns)
|
||||
{
|
||||
parser->ns = ns;
|
||||
}
|
||||
|
||||
int aml_parser_peek(struct aml_parser *parser)
|
||||
{
|
||||
if (parser->ptr >= parser->end) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
return *parser->ptr;
|
||||
}
|
||||
|
||||
int aml_parser_peek_next(struct aml_parser *parser)
|
||||
{
|
||||
if (parser->ptr + 1 >= parser->end) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
return *(parser->ptr + 1);
|
||||
}
|
||||
|
||||
int aml_parser_advance(struct aml_parser *parser)
|
||||
{
|
||||
if (parser->ptr >= parser->end) {
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
return *(parser->ptr++);
|
||||
}
|
||||
|
||||
unsigned int aml_parser_cursorpos(struct aml_parser *parser)
|
||||
{
|
||||
if (parser->ptr < parser->start) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return parser->ptr - parser->start;
|
||||
}
|
||||
|
||||
void aml_parser_save_cursor(struct aml_parser *parser)
|
||||
{
|
||||
parser->saved_ptr = parser->ptr;
|
||||
}
|
||||
|
||||
void aml_parser_load_cursor(struct aml_parser *parser)
|
||||
{
|
||||
parser->ptr = parser->saved_ptr;
|
||||
}
|
||||
|
||||
static bool object_name_is_always_root(const char *name)
|
||||
{
|
||||
return (!strcmp(name, "_SB_") || !strcmp(name, "GPE_") || !strcmp(name, "_PR_") || !strcmp(name, "_TZ_"));
|
||||
}
|
||||
|
||||
void aml_parser_add_object(struct aml_parser *parser, struct acpi_object *object)
|
||||
{
|
||||
if (object->parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *publish_path = object->publish_path;
|
||||
char *rpath = publish_path;
|
||||
|
||||
//printf("adding object '%s'. current scope=%s\n", publish_path, parser->cur_scope ? parser->cur_scope->scope_object->name : "<none>");
|
||||
|
||||
struct acpi_object *cur = parser->cur_scope ? parser->cur_scope->scope_object : NULL;
|
||||
if (*rpath == '\\') {
|
||||
cur = parser->ns->root;
|
||||
rpath++;
|
||||
}
|
||||
|
||||
char *sp;
|
||||
char *tok = strtok_r(rpath, ".", &sp);
|
||||
if (object_name_is_always_root(tok)) {
|
||||
cur = parser->ns->root;
|
||||
}
|
||||
|
||||
if (!cur) {
|
||||
fprintf(stderr, "cannot add object with relative path: no scope!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (!tok || *tok == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
char *next_tok = strtok_r(NULL, ".", &sp);
|
||||
if (!next_tok) {
|
||||
break;
|
||||
}
|
||||
|
||||
struct acpi_object *next = acpi_object_get_child(cur, tok);
|
||||
if (!next) {
|
||||
//printf("auto-creating scope '%s' under '%s'\n", tok, cur->name);
|
||||
next = acpi_object_create(tok, ACPI_OBJECT_NAMESPACE);
|
||||
acpi_object_add_child(cur, next);
|
||||
}
|
||||
|
||||
tok = next_tok;
|
||||
}
|
||||
|
||||
strncpy(object->name, tok, sizeof object->name - 1);
|
||||
object->name[sizeof object->name - 1] = '\0';
|
||||
|
||||
acpi_object_add_child(cur, object);
|
||||
free(publish_path);
|
||||
}
|
||||
|
||||
void aml_parser_push_scope(struct aml_parser *parser, struct acpi_object *object)
|
||||
{
|
||||
struct aml_parser_scope *scope = malloc(sizeof *scope);
|
||||
if (!scope) {
|
||||
perror("aml_parser_push_scope: malloc");
|
||||
abort();
|
||||
}
|
||||
|
||||
scope->scope_object = object;
|
||||
scope->scope_end = object->scope_end;
|
||||
scope->next = parser->cur_scope;
|
||||
object->scope_end = 0;
|
||||
parser->cur_scope = scope;
|
||||
|
||||
//printf("## 0x%04x: moving into scope '%s' (ends at 0x%04zx)\n", aml_parser_cursorpos(parser), parser->cur_scope->scope_object->name, scope->scope_end);
|
||||
}
|
||||
|
||||
void aml_parser_pop_scope(struct aml_parser *parser)
|
||||
{
|
||||
if (!parser->cur_scope) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(parser->cur_scope->scope_object->name, "\\") && !parser->cur_scope->next) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
printf("## 0x%04x: moving out of scope '%s' up to scope '%s' (ends at 0x%04zx)\n",
|
||||
aml_parser_cursorpos(parser),
|
||||
parser->cur_scope ? parser->cur_scope->scope_object->name : "<none>",
|
||||
parser->cur_scope->next ? parser->cur_scope->next->scope_object->name : "<none>",
|
||||
parser->cur_scope->next ? parser->cur_scope->next->scope_end : 0xFFFF);
|
||||
*/
|
||||
|
||||
struct aml_parser_scope *previous_scope = parser->cur_scope;
|
||||
parser->cur_scope = parser->cur_scope->next;
|
||||
free(previous_scope);
|
||||
}
|
||||
|
||||
static void add_object_to_parser(struct aml_parser *parser, struct acpi_object *object)
|
||||
{
|
||||
if (!object->parent && object != parser->ns->root) {
|
||||
aml_parser_add_object(parser, object);
|
||||
}
|
||||
|
||||
if (object->scope_end != 0) {
|
||||
aml_parser_push_scope(parser, object);
|
||||
}
|
||||
}
|
||||
|
||||
static bool should_pop_current_scope(struct aml_parser *parser)
|
||||
{
|
||||
if (!parser->cur_scope) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!strcmp(parser->cur_scope->scope_object->name, "\\") && !parser->cur_scope->next) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return parser->cur_scope->scope_end <= aml_parser_cursorpos(parser);
|
||||
}
|
||||
|
||||
enum parse_status aml_parser_parse_into_namespace(struct aml_parser *parser, struct acpi_namespace *ns)
|
||||
{
|
||||
parser->ns = ns;
|
||||
|
||||
while (1) {
|
||||
struct aml_value value;
|
||||
enum parse_status status = parse_opcode(parser, &value);
|
||||
if (status != PARSE_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (value.type == AML_VALUE_OBJECT) {
|
||||
struct acpi_object *object = value.value.object;
|
||||
add_object_to_parser(parser, object);
|
||||
}
|
||||
|
||||
while (should_pop_current_scope(parser)) {
|
||||
aml_parser_pop_scope(parser);
|
||||
}
|
||||
}
|
||||
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
struct acpi_object *aml_parser_resolve_path(struct aml_parser *parser, const char *path)
|
||||
{
|
||||
struct acpi_object *cur = parser->cur_scope ? parser->cur_scope->scope_object : NULL;
|
||||
if (*path == '\\') {
|
||||
path++;
|
||||
cur = parser->ns->root;
|
||||
}
|
||||
|
||||
size_t path_len = strlen(path);
|
||||
char *rpath = malloc(path_len + 1);
|
||||
strcpy(rpath, path);
|
||||
|
||||
char *sp;
|
||||
char *tok = strtok_r(rpath, ".", &sp);
|
||||
if (tok && object_name_is_always_root(tok)) {
|
||||
cur = parser->ns->root;
|
||||
}
|
||||
|
||||
if (!cur) {
|
||||
free(rpath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (tok) {
|
||||
struct acpi_object *child = acpi_object_get_child(cur, tok);
|
||||
if (!child) {
|
||||
free(rpath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cur = child;
|
||||
tok = strtok_r(NULL, ".", &sp);
|
||||
}
|
||||
|
||||
free(rpath);
|
||||
return cur;
|
||||
}
|
||||
|
||||
#define STATUS_STRING(code) \
|
||||
case code: \
|
||||
return #code;
|
||||
|
||||
const char *parse_status_string(enum parse_status status)
|
||||
{
|
||||
switch (status) {
|
||||
STATUS_STRING(PARSE_OK)
|
||||
STATUS_STRING(PARSE_EOF)
|
||||
STATUS_STRING(PARSE_NOMEM)
|
||||
STATUS_STRING(PARSE_BADSTRING)
|
||||
STATUS_STRING(PARSE_UNKNOWNOP)
|
||||
STATUS_STRING(PARSE_BADTYPE)
|
||||
STATUS_STRING(PARSE_BADREF)
|
||||
default:
|
||||
return "<unknown>";
|
||||
}
|
||||
}
|
||||
48
tools/amldecode/aml/parser.h
Normal file
48
tools/amldecode/aml/parser.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef AML_PARSER_H_
|
||||
#define AML_PARSER_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
struct acpi_namespace;
|
||||
|
||||
enum parse_status {
|
||||
PARSE_OK = 0,
|
||||
PARSE_EOF = -1,
|
||||
PARSE_NOMEM = -2,
|
||||
PARSE_BADSTRING = -3,
|
||||
PARSE_UNKNOWNOP = -4,
|
||||
PARSE_BADTYPE = -5,
|
||||
PARSE_BADREF = -6,
|
||||
};
|
||||
|
||||
struct aml_parser_scope {
|
||||
struct acpi_object *scope_object;
|
||||
size_t scope_end;
|
||||
struct aml_parser_scope *next;
|
||||
};
|
||||
|
||||
struct aml_parser {
|
||||
unsigned char *start, *end;
|
||||
unsigned char *ptr, *saved_ptr;
|
||||
struct acpi_namespace *ns;
|
||||
struct aml_parser_scope *cur_scope;
|
||||
};
|
||||
|
||||
extern void aml_parser_init(struct aml_parser *parser, void *p, size_t len);
|
||||
extern void aml_parser_set_namespace(struct aml_parser *parser, struct acpi_namespace *ns);
|
||||
extern int aml_parser_peek(struct aml_parser *parser);
|
||||
extern int aml_parser_peek_next(struct aml_parser *parser);
|
||||
extern int aml_parser_advance(struct aml_parser *parser);
|
||||
extern unsigned int aml_parser_cursorpos(struct aml_parser *parser);
|
||||
extern void aml_parser_save_cursor(struct aml_parser *parser);
|
||||
extern void aml_parser_load_cursor(struct aml_parser *parser);
|
||||
extern void aml_parser_add_object(struct aml_parser *parser, struct acpi_object *object);
|
||||
extern void aml_parser_push_scope(struct aml_parser *parser, struct acpi_object *object);
|
||||
extern void aml_parser_pop_scope(struct aml_parser *parser);
|
||||
|
||||
extern enum parse_status aml_parser_parse_into_namespace(struct aml_parser *parser, struct acpi_namespace *ns);
|
||||
extern struct acpi_object *aml_parser_resolve_path(struct aml_parser *parser, const char *path);
|
||||
|
||||
extern const char *parse_status_string(enum parse_status status);
|
||||
|
||||
#endif
|
||||
17
tools/amldecode/aml/value.c
Normal file
17
tools/amldecode/aml/value.c
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "value.h"
|
||||
|
||||
uint64_t aml_value_get_integer(const struct aml_value *value)
|
||||
{
|
||||
switch (value->type) {
|
||||
case AML_VALUE_UINT8:
|
||||
return value->value.uint8;
|
||||
case AML_VALUE_UINT16:
|
||||
return value->value.uint8;
|
||||
case AML_VALUE_UINT32:
|
||||
return value->value.uint8;
|
||||
case AML_VALUE_UINT64:
|
||||
return value->value.uint8;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
43
tools/amldecode/aml/value.h
Normal file
43
tools/amldecode/aml/value.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef AML_VALUE_H_
|
||||
#define AML_VALUE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "constants.h"
|
||||
|
||||
struct acpi_object;
|
||||
|
||||
enum aml_value_type {
|
||||
AML_VALUE_NONE,
|
||||
AML_VALUE_UINT8,
|
||||
AML_VALUE_UINT16,
|
||||
AML_VALUE_UINT32,
|
||||
AML_VALUE_UINT64,
|
||||
AML_VALUE_OBJECT,
|
||||
AML_VALUE_NAME,
|
||||
AML_VALUE_STRING,
|
||||
};
|
||||
|
||||
struct aml_value {
|
||||
enum aml_value_type type;
|
||||
|
||||
union {
|
||||
uint8_t uint8;
|
||||
uint16_t uint16;
|
||||
uint32_t uint32;
|
||||
uint64_t uint64;
|
||||
struct acpi_object *object;
|
||||
const char *name;
|
||||
const char *str;
|
||||
} value;
|
||||
};
|
||||
|
||||
static inline bool aml_value_is_integer(const struct aml_value *value)
|
||||
{
|
||||
return value->type == AML_VALUE_UINT8 || value->type == AML_VALUE_UINT16 || value->type == AML_VALUE_UINT32 || value->type == AML_VALUE_UINT64;
|
||||
}
|
||||
|
||||
extern uint64_t aml_value_get_integer(const struct aml_value *value);
|
||||
extern void aml_value_destroy(struct aml_value *value);
|
||||
|
||||
#endif
|
||||
154
tools/amldecode/main.c
Normal file
154
tools/amldecode/main.c
Normal file
@@ -0,0 +1,154 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "aml/parser.h"
|
||||
#include "aml/object.h"
|
||||
#include "table.h"
|
||||
|
||||
/*
|
||||
static struct acpi_table_header *read_table(FILE *fp)
|
||||
{
|
||||
fseek(fp, 0, SEEK_END);
|
||||
size_t len = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
struct acpi_table_header *table = malloc(len);
|
||||
if (!table) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fread(table, 1, len, fp);
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "usage: %s <AML file>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *filepath = argv[1];
|
||||
FILE *fp = fopen(filepath, "rb");
|
||||
if (!fp) {
|
||||
perror("open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct acpi_table_header *table = read_table(fp);
|
||||
fclose(fp);
|
||||
|
||||
if (!table) {
|
||||
perror("read_table");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct aml_object *root;
|
||||
|
||||
parse_aml(table, &root);
|
||||
|
||||
printf("\n\n");
|
||||
aml_object_print(root, 0);
|
||||
free(table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
static struct acpi_namespace *create_test_namespace(void)
|
||||
{
|
||||
struct acpi_namespace *ns = acpi_namespace_create();
|
||||
|
||||
struct acpi_object *root = acpi_object_create("\\", ACPI_OBJECT_NAMESPACE);
|
||||
ns->root = root;
|
||||
|
||||
struct acpi_object *pr = acpi_object_create("_PR", ACPI_OBJECT_NAMESPACE);
|
||||
struct acpi_object *cpu0 = acpi_object_create("CPU0", ACPI_OBJECT_CPU);
|
||||
acpi_object_add_child(pr, cpu0);
|
||||
|
||||
struct acpi_object *sb = acpi_object_create("_SB", ACPI_OBJECT_NAMESPACE);
|
||||
struct acpi_object *lid0 = acpi_object_create("LID0", ACPI_OBJECT_DEVICE);
|
||||
struct acpi_object *lid0_hid = acpi_object_create("_HID", ACPI_OBJECT_VALUE);
|
||||
struct acpi_object *lid0_sta = acpi_object_create("_STA", ACPI_OBJECT_METHOD);
|
||||
acpi_object_add_child(lid0, lid0_hid);
|
||||
acpi_object_add_child(lid0, lid0_sta);
|
||||
|
||||
struct acpi_object *pci0 = acpi_object_create("PCI0", ACPI_OBJECT_DEVICE);
|
||||
struct acpi_object *pci0_hid = acpi_object_create("_HID", ACPI_OBJECT_VALUE);
|
||||
struct acpi_object *pci0_cid = acpi_object_create("_CID", ACPI_OBJECT_VALUE);
|
||||
struct acpi_object *pci0_rp03 = acpi_object_create("RP03", ACPI_OBJECT_NAMESPACE);
|
||||
struct acpi_object *pci0_rp03_pxp3 = acpi_object_create("PXP3", ACPI_OBJECT_POWER_RESOURCE);
|
||||
struct acpi_object *pci0_gfx0 = acpi_object_create("GFX0", ACPI_OBJECT_DEVICE);
|
||||
struct acpi_object *pci0_gfx0_adr = acpi_object_create("_ADR", ACPI_OBJECT_VALUE);
|
||||
struct acpi_object *pci0_gfx0_dd01 = acpi_object_create("DD01", ACPI_OBJECT_DEVICE);
|
||||
struct acpi_object *pci0_gfx0_dd01_bcl = acpi_object_create("_BCL", ACPI_OBJECT_METHOD);
|
||||
acpi_object_add_child(pci0_gfx0_dd01, pci0_gfx0_dd01_bcl);
|
||||
acpi_object_add_child(pci0_gfx0, pci0_gfx0_adr);
|
||||
acpi_object_add_child(pci0_gfx0, pci0_gfx0_dd01);
|
||||
acpi_object_add_child(pci0_rp03, pci0_rp03_pxp3);
|
||||
acpi_object_add_child(pci0, pci0_hid);
|
||||
acpi_object_add_child(pci0, pci0_cid);
|
||||
acpi_object_add_child(pci0, pci0_rp03);
|
||||
acpi_object_add_child(pci0, pci0_gfx0);
|
||||
|
||||
acpi_object_add_child(sb, lid0);
|
||||
acpi_object_add_child(sb, pci0);
|
||||
|
||||
struct acpi_object *tz = acpi_object_create("_TZ", ACPI_OBJECT_NAMESPACE);
|
||||
struct acpi_object *tz_fn00 = acpi_object_create("FN00", ACPI_OBJECT_POWER_RESOURCE);
|
||||
struct acpi_object *tz_fan0 = acpi_object_create("FAN0", ACPI_OBJECT_DEVICE);
|
||||
struct acpi_object *tz_fan0_hid = acpi_object_create("_HID", ACPI_OBJECT_VALUE);
|
||||
struct acpi_object *tz_tz00 = acpi_object_create("TZ00", ACPI_OBJECT_THERMAL_ZONE);
|
||||
acpi_object_add_child(tz_fan0, tz_fan0_hid);
|
||||
acpi_object_add_child(tz, tz_fn00);
|
||||
acpi_object_add_child(tz, tz_fan0);
|
||||
acpi_object_add_child(tz, tz_tz00);
|
||||
|
||||
struct acpi_object *gpe = acpi_object_create("_GPE", ACPI_OBJECT_NAMESPACE);
|
||||
|
||||
acpi_object_add_child(root, pr);
|
||||
acpi_object_add_child(root, sb);
|
||||
acpi_object_add_child(root, tz);
|
||||
acpi_object_add_child(root, gpe);
|
||||
|
||||
return ns;
|
||||
}
|
||||
*/
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "usage: %s <AML file>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct acpi_table *table;
|
||||
enum loader_status loader_status = acpi_table_load(argv[1], &table);
|
||||
if (loader_status != LOADER_OK) {
|
||||
fprintf(stderr, "cannot load '%s': %s\n", argv[1], loader_status_string(loader_status));
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *table_payload;
|
||||
size_t payload_len;
|
||||
acpi_table_get_payload(table, &table_payload, &payload_len);
|
||||
|
||||
struct acpi_namespace *ns = acpi_namespace_create();
|
||||
|
||||
struct aml_parser parser;
|
||||
aml_parser_init(&parser, table_payload, payload_len);
|
||||
|
||||
enum parse_status parser_status = aml_parser_parse_into_namespace(&parser, ns);
|
||||
if (parser_status != PARSE_OK) {
|
||||
fprintf(stderr, "error occurred while parsing '%s': %s\n", argv[1], parse_status_string(parser_status));
|
||||
}
|
||||
|
||||
if (ns->root) {
|
||||
acpi_object_print(ns->root, 0);
|
||||
}
|
||||
|
||||
acpi_table_destroy(table);
|
||||
return parser_status == PARSE_OK ? 0 : -1;
|
||||
}
|
||||
72
tools/amldecode/table.c
Normal file
72
tools/amldecode/table.c
Normal file
@@ -0,0 +1,72 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "table.h"
|
||||
|
||||
enum loader_status acpi_table_load(const char *path, struct acpi_table **out)
|
||||
{
|
||||
FILE *fp = fopen(path, "rb");
|
||||
if (!fp) {
|
||||
return LOADER_IOERR;
|
||||
}
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
size_t len = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
unsigned char *buf = malloc(len);
|
||||
if (!buf) {
|
||||
fclose(fp);
|
||||
return LOADER_NOMEM;
|
||||
}
|
||||
|
||||
size_t r = fread(buf, 1, len, fp);
|
||||
if (r != len) {
|
||||
free(buf);
|
||||
fclose(fp);
|
||||
return LOADER_IOERR;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
size_t sum = 0;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
sum += buf[i];
|
||||
}
|
||||
|
||||
if ((sum % 0x100) != 0) {
|
||||
free(buf);
|
||||
return LOADER_BADSUM;
|
||||
}
|
||||
|
||||
struct acpi_table *table = (struct acpi_table *)buf;
|
||||
*out = table;
|
||||
|
||||
return LOADER_OK;
|
||||
}
|
||||
|
||||
void acpi_table_destroy(struct acpi_table *table)
|
||||
{
|
||||
free(table);
|
||||
}
|
||||
|
||||
void acpi_table_get_payload(struct acpi_table *table, void **p, size_t *len)
|
||||
{
|
||||
*p = (unsigned char *)table + sizeof *table;
|
||||
*len = table->length;
|
||||
}
|
||||
|
||||
#define STATUS_STRING(code) \
|
||||
case code: \
|
||||
return #code;
|
||||
|
||||
const char *loader_status_string(enum loader_status status)
|
||||
{
|
||||
switch (status) {
|
||||
STATUS_STRING(LOADER_OK)
|
||||
STATUS_STRING(LOADER_IOERR)
|
||||
STATUS_STRING(LOADER_BADSUM)
|
||||
STATUS_STRING(LOADER_NOMEM)
|
||||
default:
|
||||
return "<unknown>";
|
||||
}
|
||||
}
|
||||
32
tools/amldecode/table.h
Normal file
32
tools/amldecode/table.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef TABLE_H_
|
||||
#define TABLE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
enum loader_status {
|
||||
LOADER_OK = 0,
|
||||
LOADER_IOERR,
|
||||
LOADER_BADSUM,
|
||||
LOADER_NOMEM,
|
||||
};
|
||||
|
||||
struct acpi_table {
|
||||
char sig[4];
|
||||
uint32_t length;
|
||||
uint8_t revision;
|
||||
uint8_t checksum;
|
||||
char oem_id[6];
|
||||
char oem_table_id[8];
|
||||
uint32_t oem_revision;
|
||||
uint32_t creator_id;
|
||||
uint32_t creator_revision;
|
||||
};
|
||||
|
||||
extern enum loader_status acpi_table_load(const char *path, struct acpi_table **out);
|
||||
extern void acpi_table_destroy(struct acpi_table *table);
|
||||
extern void acpi_table_get_payload(struct acpi_table *table, void **p, size_t *len);
|
||||
|
||||
extern const char *loader_status_string(enum loader_status status);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user