acpi aml and acpica

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

acpi aml and acpica

Post by h0bby1 »

ok i'm getting a bit into acpi, i guess i could live without it but i'm going to get a shot at getting it running, i'm mostly interested into the device tree to get pci interupt from the acpi tables, more than about power mannagement events, and more complex stuff, i just started to get into it today with the help of the wiki and the forum and swallowed the 1000 page spec, started to fetch the acpi tables, but seem all the really usefull information are stored as aml files that need to be dissambled, so it seem a bit hell but i'm going to get a shot at it

so i downloaded acpica, and got to compile with visual under windows, just had to compile few stuff under linux because it use yacc and bison to build some files needed for the build , so far so good even if the makefile seem rather horrendous, they just pick files in the directories depending on the build, and the makefile contain a big list of .o file to build, and if you build files from the directories that are not in the makefile , some symbols are defined twice, so the design seem a bit poor but i got it to compile the iasl with visual and it seem to works for now

now what bother me, the isal is 500k at this point it's half the size of my os including usb, audio, memory allocation, ndis emulation layer, file system and all so it's bit bothering me, and i'm going to try to cut it down to have just the part that dissemble the aml from memory, and cut down the compile and file management, and also trying to get rid of all the awfull global variable ,cause my abi doesn't support non initialised section for the moment, and i don't like the principle to have global variable specially i'll probably compile it to a dll, so i'll try to cut it down to minimum for just dissembly of aml code from memory, and cut down os dependency as well, i just looked at the code quickly to get it to compile under visual, it seem doable for the moment i'll see how that goes

i know it's under license, i'm not a lawyer, so i don't know if it's even supposed to be legal to extract code, but i'm pretty used to do that kind of thing on many library, it will probably take me some time, but i think i'll figure it out and get it to minimum for dissambly, did anyone even got into acpica library a bit in depth, or already tried to do that, or would know otherwise other library that are lighter and could just disassemble the aml from memory in a simpler/cleaner way than the iasl ?

it doesn't seem that complicated for the moment, apparently the main entry point to dissasemble from memory are

Code: Select all

/******************************************************************************
 *
 * FUNCTION:    AdParseTable
 *
 * PARAMETERS:  Table               - Pointer to the raw table
 *              OwnerId             - Returned OwnerId of the table
 *              LoadTable           - If add table to the global table list
 *              External            - If this is an external table
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Parse the DSDT.
 *
 *****************************************************************************/

ACPI_STATUS
AdParseTable (
    ACPI_TABLE_HEADER       *Table,
    ACPI_OWNER_ID           *OwnerId,
    BOOLEAN                 LoadTable,
    BOOLEAN                 External)

Code: Select all

/*******************************************************************************
 *
 * FUNCTION:    AcpiDmFinishNamespaceLoad
 *
 * PARAMETERS:  ParseTreeRoot       - Root of the parse tree
 *              NamespaceRoot       - Root of the internal namespace
 *              OwnerId             - OwnerId of the table to be disassembled
 *
 * RETURN:      None
 *
 * DESCRIPTION: Load all namespace items that are created within control
 *              methods. Used before namespace cross reference
 *
 ******************************************************************************/

void
AcpiDmFinishNamespaceLoad (
    ACPI_PARSE_OBJECT       *ParseTreeRoot,
    ACPI_NAMESPACE_NODE     *NamespaceRoot,
    ACPI_OWNER_ID           OwnerId)
and a little bunch of other function of which api doesn't seem to be all that bad, i'll cut also all the debug things and useless stuff to see where it can get, removed all the debug things, and the file management, it doesn't seem that hardcore, now i'm not interested into full handling of the whole asl thing, just parsing device tree and getting pci irq things mostly, so it shouldn't be too too hard to get that to work, wonder if someone already tried that or what you think about it ?

basically my goal would be more or less to rewrite this function and use it as entry point in a dynamically linked library, but without anykind of file input/output, just using directly the table fetching and output to a memory buffer

Code: Select all

/******************************************************************************
 *
 * FUNCTION:    AdAmlDisassemble
 *
 * PARAMETERS:  Filename            - AML input filename
 *              OutToFile           - TRUE if output should go to a file
 *              Prefix              - Path prefix for output
 *              OutFilename         - where the filename is returned
 *              GetAllTables        - TRUE if all tables are desired
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Disassemble an entire ACPI table
 *
 *****************************************************************************/

ACPI_STATUS
AdAmlDisassemble (
    BOOLEAN                 OutToFile,
    char                    *Filename,
    char                    *Prefix,
    char                    **OutFilename,
    BOOLEAN                 GetAllTables)

User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: acpi aml and acpica

Post by Owen »

Why are you trying to dissassemble the AML to ASL?

Doing that might be useful to you, that lump of gray matter between your ears... but not very useful to your OS, which finds a textual description of the _PRT function even less useful for telling it IRQ routing than the binary version.

You need to execute the appropriate AML methods... and notify the AML that you're in APIC mode, for a start
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: acpi aml and acpica

Post by h0bby1 »

Owen wrote:Why are you trying to dissassemble the AML to ASL?

Doing that might be useful to you, that lump of gray matter between your ears... but not very useful to your OS, which finds a textual description of the _PRT function even less useful for telling it IRQ routing than the binary version.

You need to execute the appropriate AML methods... and notify the AML that you're in APIC mode, for a start
but i need to dissasemble it to parse it no ? if i dissasemble it and parse what i need from it, it's all i need no ? it should contain a description of the machine, device etc according to what i think i understood from the spec

normally it should be executed, with events for power up/down etc, but it contain a description of the machine as well, including hierarchy of device drivers etc

but maybe it's not possible to extract easily meaningfull information this way if i parse quickly the information i need from it, and it's better to execute it directly as binary code, provided i don't need power management and event execution things ?
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: acpi aml and acpica

Post by h0bby1 »

ok i advanced a bit on this, i got it to compile as a minimal version, the exe is now about 120K (about 50K compressed), the whole part of compile asl is removed, so it can only disassemble binary aml files now, and i reduced the dependency it doesn't use stdio at all anymore, and only use a little set of libc function to dissasemble aml from/to memory

it only need these functions to link and the output seem conform to the output from iasl, so, so far so good

Code: Select all

__imp__isprint_c	
__imp__isalpha_c	
__imp__isxdigit_c
__imp__isdigit_c
__imp__strcat_c
__imp__strncat_c	
__imp__strlen_c
__imp__strcmp_c		
__imp__strcpy_c		
__imp__strncpy_c
__imp__memcpy_c
__imp__toupper_c	
__imp__memset_c
__imp__tolower_c	
__imp__isspace_c	
__imp__memcmp_c		
__imp__strncmp_c	
__imp__writeptr		
__imp__writestr		
__imp__writeint		
__imp__malloc_c		
__imp__free_c		
__imp__snooze	

but the output asl still seem to be non trival to parse, in virtual box the bytecode is only a few dizains of bytes long, on my computer it's another story, it doesn't look all that hard to make sense of, it's just definition of block of information and methods, but there is a system of conditional execution and environment variable, and still a number of possible operation and opcode, not sure it will really be uefull as it, and it take about 10-20 sec to disassemble the aml from my comp, to output a 10 000l ascii file of asl definition, it does contain the _prt method for some device with the good synthax of information, but even the global synthax of how devices are supposed to be represented is not all that clear and straigthforward, in anyway i'll have it in case for debug purpose to be able to visualize the acpi configuration file if there is some problem, but i guess it's wiser to do the aml bytecode execution/parsing way rather than disassembling the aml and parsing the result, so i'll try to get a minimal aml bytecode parser running, and keep the aml disassembly as a debugging tool i guess
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: acpi aml and acpica

Post by h0bby1 »

my rant about acpica lib still :D

it use lot of conditional compilation , many file have some function enabled with preeprocessor definition, and compiled differently depending on which project is built, some function can be defined in several file and compiled from the right one depending on preprocessor definition, i find this kind of things really awfull, if some code is specific to a particular build, it's way cleaner to have a version of the file for the code that differ for each build, than enabling the compilation of some functions from different file with preprocessor configuration, it's a trend i never really get with open source type of code to use lot of preprocessor definition like that, it make the compilation process very tricky, and can lead to many mistake, i think it show very poor design in term of dependency and global modular design, it links an hundred of file compiled conditionally in a big static exe, and i don't like the way it's made
#
# Note: This makefile is intended to be used from within the native
# ACPICA directory structure, from under generate/unix. It specifically
# places all object files in a generate/unix subdirectory, not within
# the various ACPICA source directories. This prevents collisions
# between different compilations of the same source file with different
# compile options,
and prevents pollution of the source code.
at least they warn that their building method is not very clean =)

otherwise good point is they still handled some things that make it easy to port, all call to libcs are done via macros and include to stdlib function are also easy to locate and remove, (mostly in acpica-unix-20130823\source\include\platform\acenv.h ), but they still make use of stdio function for most of the output, i had to manually breaks stdio function to output with direct call to print_str,print_int,print char, and i'll have to redicted the output to a memory stream like structure to store the output, it was not to hard to do as call to libc and system calls are already centralized, so that's already a good point, i still have to remove the global variables as well and i'll try to pass them as a caller supplied structure, at least for the non const non initialized global variables, but already removing file managment from it reduce the use of global variable, but i still have a bit of clean up to do to get it work how i want

then i'll try to see what the bytecode interpreter looks like, lot of code is common to all the part of the lib, so there is already good part of the parsing function that are already compiled, maybe i'll try to make a bit of organisation into the build to have the common part as a dynamic library if i can figure out the whole conditional compilation logic of the thing
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: acpi aml and acpica

Post by Owen »

Why are you trying to link any of the bits which do string processing and/or I/O to your kernel?

Those bits exist for the AML compiler/decompiler. No kernel needs nor wants those bits; they're for the iasl utility.

You want the table parser and VM, and thats it. Those bits have literally no outside dependencies except the AcpicaOs** functions.
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: acpi aml and acpica

Post by h0bby1 »

Owen wrote:Why are you trying to link any of the bits which do string processing and/or I/O to your kernel?

Those bits exist for the AML compiler/decompiler. No kernel needs nor wants those bits; they're for the iasl utility.

You want the table parser and VM, and thats it. Those bits have literally no outside dependencies except the AcpicaOs** functions.
i advanced a bit more int it, but the things is i'm not sure i really want the acpica to handle everything it's supposed to handle, i still have to dig the lib to understand exactly how it's supposed to work, but from what i understand, the aml language can contain instruction to manipulate device io , and require an exclusive access to them, even drivers are then supposed to use acpi driver layer?

from what i understand, there is a whole part that is made to load table from the system, and store them into global memory, either as file list or as pointer to the acpi table data using other variable, then there is a part that parse the aml, here it differ depending if the lib is compiled as the compiler/dissambler or executer, the aml doesn't seem to be processed exactly in the same way depending on the compile option, i don't think there are mutually exclusive part, but maybe the code is not supposd to be compiled to be used both with compiling/disassembling and executing, there is a config flag called 'NO_METHOD_EXECUTION' and another 'ACPI_CONSTANT_EVAL_ONLY', the last one is supposed to be defined automatically when 'ACPI_ASL_COMPILER' is set, and both influence how the parser intialize it's structure from the aml code, as the compiler is not supposed to have to deal with thread, mutex, and event handling, and whole lot of things, that i'm not really sure i even want to deal with if it's not necessary for what i want to do

i think the aml thing is a good things, i like what it allow to do, and the parser part of acpica still seem rather nicely done, i'm sure the same code can be used at the end of the day to just display disassembly output and executing it, but i'd rather then handle the actions it require in another way than the actual executer, maybe i'd store the parsed aml somewhere , and store what i need to identify and execute aml function from a device in a device related structure, or get closer to the executer part of the library to handle the commands at lower level, but i'm not sure it's even possible to do that, there is a flag also 'REDUCED_HARDWARE' who doesn't compile any of the hardware related code, it's close to the function i'd want, but then the aml code dealing with hardware request will just be disabled, which is not what i want

ideally i'd like to more being able to execute at least some part of the aml things, but without letting the acpica lib doing the whole thing in the background and let it have an exclusive access to the hardware it handle, but i'm not sure it's even possible and reliable to handle all part of acpi like that

in the absolute the only thing i really want to do, is to be able to fetch the device information defined through the aml, but i understand that all definition are made dynamically and the informations is supposed to be used after the code is correctly initialized with some system relative variable and eveyrthing is supposed to be manipulated through execution of some aml code, and the ouput of those function are made with conditional execution, so i still need to parse and execute aml to be able to do anything usefull with it, but i'm not sure i want to let acpica handle the whole thing of event/lock/multihreading and exclusive acess on hardware for that

in the absolute if i use the acpi system very early just to get the infos it want at initialisation stage, and that it really need to have multi threaded event handling and mutex and exclusive acess to execute and that i can make sure it doesn't change important things in the hardware, it can be executed like that at init and then shutdown, but i'd rather avoid to have apcica to handle many things it's supposed to handle with aml code execution
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: acpi aml and acpica

Post by h0bby1 »

i looked for other options than acpica, i found this

https://svn.code.sf.net/p/edk2/code/tru ... rsal/Acpi/

it's supposed to be a framework related to UEFI/PI specification, so i'm not even sure i really understand what it's supposed to be about, but it seem to contain what it need to parse aml file in a much more straightforward and simpler way than the acpica, it seem to only handle a reduced set of feature,and it doesn't seem to provide the support for the whole execution framework and event handling like acpica, and i'm not sure how reliable this lib is supposed be, but it's developped by intel under bsd license, and it probably still follow spec for opcode and aml bytecode managment

it can just load up table and opcode tree in a way that seem similar to acpica, and there are function to read data and objects defined in the aml, apparently the lib seem to support the execution of _S3 to enter suspend/resume state, it seem much less complete in the handling of the whole acpi like acpica, but it still provide for a framework to deal with acpi table, parse aml bytecode, and retrieve data object from it, and it's very simple, i'm not sure it can really execute method in the aml, or what it's supposed to be handling correctly, but it's closer to how i'd like the aml parser to function

with acpica, their design seem to be to handle everything in background, and provide a complex mechanism of event handling wtith call back to interface with the rest of the system, but the 'os independance' is really only on a pure language/call level, because it involve a whole lot of complexity in the conceptual aspect of what it's supposed to do, and the call back mechanism doesn't seem to provide with lot of information on the context from which the call back is being called, or what is actually going on behind the actual os call

specially as it involve a multi layered mutex system and multi threading, and that the function can be doing pretty much anything on the system, it seem a rather poor way to handle "os independance" to just implement a bunch of call back to do this or that without the os has any way to know what is going on conceptually behind

i saw there is a way to pass the functiun for handling io acess to device drivers, but if the drivers call back is being called saying it need to access this register at this io location, and the callback doesn't contain sufficient context information, the driver doesn't know what is actually going on and why he is supposed to change the register value, and the device drivers do not really understand the whole conceptual information of what it is asked to do, so i find this a bit weird

regarding the complexity of what is being handled by the aml execution in acpica, i don't find that just providing the interface to setup a mutex is really enough to call it really and truly os independant, as it still imply that the os designer must know how acpi works, and what acpica can be doing, and there is a whole level of complexity involved in the execution that cannot be really integrated into the os via the acpios api, as the api is rather only low level things and do not really provide the os with a more conceptual information of what is going on behind

they say in the documentation of acpica that the lowest level functions of the parser/executer are not supposed to be used directly, so it explictly ask for a totally blind execution of the whole aml thing by the os, including io/memory access, and setting up a whole lot of hardware related thing, in a way that the os doesn't have any higher level conceptual information of what is being done, i find this a bit weird in the concept

specially that the information contained in aml/asl files doesn't seem that complex, from what i understood from the acpica documentation, the whole multi threading thing is mostly used in case an aml function could block, to schedule the execution of another method in a queue, but they say somewhere in the absolute there is no real need for multhreading to implement a valid aml parser, and normally there is absolutly never two method that are executed at the same time, another method can be executed only when a method block, then the control is given to the execution of another method until the first method release the block , but normally there is no real need to have two method executed in the same time

they still say that event handling should be enabled and the acpi hardware functional before any execution of aml code is attempted, because some method can wait for the SCI or an event handler to return before to continue executions, but the question i wonder is do i really need to be able to execute any method to be able to retrieve the data objects defined in the aml, mostly regarding ressource and interupt information, or even if some opcode really need some syncrhonous interaction with the system, there should be way to implement a much simpler system than the acpica
mistergabe
Posts: 5
Joined: Sun Sep 08, 2013 8:10 am

Re: acpi aml and acpica

Post by mistergabe »

I have acpica working in my os...here is a snippet of code that initializes everything...its really easy.

Code: Select all


static ACPI_STATUS set_apic_mode(UINT64 mode)
{
	ACPI_OBJECT arg1;
	ACPI_OBJECT_LIST args;
	ACPI_STATUS ret;

	/*
	 * 0 = PIC
	 * 1 = APIC
	 * 2 = SAPIC ?
	 */
	arg1.Type = ACPI_TYPE_INTEGER;
	arg1.Integer.Value = mode;
	args.Count = 1;
	args.Pointer = &arg1;

	if (ACPI_FAILURE(ret = AcpiEvaluateObject(ACPI_ROOT_OBJECT, "_PIC", &args, NULL))) {
		return ret;
	}

	return AE_OK;
}

        ACPI_STATUS ret;

	if (ACPI_FAILURE(ret = AcpiInitializeSubsystem())) {
		kprintf("ACPI INIT failure %s\n", AcpiFormatException(ret));
		return -1;
	}

	if (ACPI_FAILURE(ret = AcpiInitializeTables(NULL, 0, FALSE))) {
		kprintf("ACPI INIT tables failure %s\n", AcpiFormatException(ret));
		return -1;
	}

	page_map(0xFEC00000, 0xFEC00000);
	if (ACPI_FAILURE(ret = AcpiLoadTables())) {
		kprintf("ACPI load tables failure %s\n", AcpiFormatException(ret));
		return -1;
	}

	if (ACPI_FAILURE(ret = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION))) {
		kprintf("ACPI enable failure %s\n", AcpiFormatException(ret));
		return -1;
	}

	if (ACPI_FAILURE(ret = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION))) {
		kprintf("ACPI init objects failure %s\n", AcpiFormatException(ret));
		return -1;
	}

	set_apic_mode(2);
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: acpi aml and acpica

Post by h0bby1 »

mistergabe wrote:I have acpica working in my os...here is a snippet of code that initializes everything...its really easy.

Code: Select all


static ACPI_STATUS set_apic_mode(UINT64 mode)
{
	ACPI_OBJECT arg1;
	ACPI_OBJECT_LIST args;
	ACPI_STATUS ret;

	/*
	 * 0 = PIC
	 * 1 = APIC
	 * 2 = SAPIC ?
	 */
	arg1.Type = ACPI_TYPE_INTEGER;
	arg1.Integer.Value = mode;
	args.Count = 1;
	args.Pointer = &arg1;

	if (ACPI_FAILURE(ret = AcpiEvaluateObject(ACPI_ROOT_OBJECT, "_PIC", &args, NULL))) {
		return ret;
	}

	return AE_OK;
}

        ACPI_STATUS ret;

	if (ACPI_FAILURE(ret = AcpiInitializeSubsystem())) {
		kprintf("ACPI INIT failure %s\n", AcpiFormatException(ret));
		return -1;
	}

	if (ACPI_FAILURE(ret = AcpiInitializeTables(NULL, 0, FALSE))) {
		kprintf("ACPI INIT tables failure %s\n", AcpiFormatException(ret));
		return -1;
	}

	page_map(0xFEC00000, 0xFEC00000);
	if (ACPI_FAILURE(ret = AcpiLoadTables())) {
		kprintf("ACPI load tables failure %s\n", AcpiFormatException(ret));
		return -1;
	}

	if (ACPI_FAILURE(ret = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION))) {
		kprintf("ACPI enable failure %s\n", AcpiFormatException(ret));
		return -1;
	}

	if (ACPI_FAILURE(ret = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION))) {
		kprintf("ACPI init objects failure %s\n", AcpiFormatException(ret));
		return -1;
	}

	set_apic_mode(2);
yes i'm not saying the basics is not easy to implement, but the way it works behind is still hard to make sense of, i'm still unsure how i want to handle this, but i'll more go the way to try to use the aml interpreter of edk 2 at least to parse the data structure, and i'll how far i want to go in implementing everything, but i don't think i want to use the whole acpica thing, it's still quite heavy, it use multi threading, and whole execution process seems rather complex/heavy for what i need from it, with 3 level lock and mutex and require synchronised access with the os for many things, i don't think i really want this
Post Reply