123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881 |
- /*++
- Copyright (c) 2012 Minoca Corp. All Rights Reserved
- Module Name:
- aml.c
- Abstract:
- This module implements the ACPI AML interpreter.
- Author:
- Evan Green 13-Nov-2012
- Environment:
- Kernel
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/kernel/driver.h>
- #include "acpip.h"
- #include "amlos.h"
- #include "amlops.h"
- #include "namespce.h"
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // Define AML execution options.
- //
- //
- // Set this bit to actually execute the given definition block.
- //
- #define AML_EXECUTION_OPTION_RUN 0x00000001
- //
- // Set this bit to print out the definition block to the debugger.
- //
- #define AML_EXECUTION_OPTION_PRINT 0x00000002
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- /*++
- Structure Description:
- This structure stores information about a loaded SSDT table.
- Members:
- ListEntry - Stores pointers to the next and previous secondary definition
- tables.
- HandleObject - Stores the optional handle associated with this definition
- block.
- ObjectList - Stores the head of the list of namespace objects to destroy if
- this definition block is unloaded. The objects on this list will be
- ACPI objects, and the list entry is the destructor list entry.
- Code - Stores the AML code for this definition block.
- --*/
- typedef struct _ACPI_LOADED_DEFINITION_BLOCK {
- LIST_ENTRY ListEntry;
- PACPI_OBJECT HandleObject;
- LIST_ENTRY ObjectList;
- PDESCRIPTION_HEADER Code;
- } ACPI_LOADED_DEFINITION_BLOCK, *PACPI_LOADED_DEFINITION_BLOCK;
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- PAML_EXECUTION_CONTEXT
- AcpipCreateAmlExecutionContext (
- ULONG Options
- );
- VOID
- AcpipDestroyAmlExecutionContext (
- PAML_EXECUTION_CONTEXT Context
- );
- KSTATUS
- AcpipExecuteAml (
- PAML_EXECUTION_CONTEXT Context
- );
- KSTATUS
- AcpipCreateNextStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT *NextStatement
- );
- VOID
- AcpipDestroyStatement (
- PAML_STATEMENT Statement
- );
- KSTATUS
- AcpipEvaluateStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- );
- PAML_STATEMENT
- AcpipCreateStatement (
- );
- KSTATUS
- AcpipCreateExecutingMethodStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT *NextStatement
- );
- KSTATUS
- AcpipRunInitializationMethods (
- PACPI_OBJECT RootObject
- );
- KSTATUS
- AcpipRunDeviceInitialization (
- PACPI_OBJECT Device,
- PBOOL TraverseDown
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // Define a value that can be set from the debugger to change the behavior
- // of the AML interpreter. For example, it can be set to print out the
- // statements it's executing. See AML_EXECUTION_OPTION_* definitions.
- //
- ULONG AcpiDebugExecutionOptions = 0x0;
- //
- // Store the list of SSDT definition blocks.
- //
- LIST_ENTRY AcpiLoadedDefinitionBlockList;
- //
- // ------------------------------------------------------------------ Functions
- //
- KSTATUS
- AcpiLoadDefinitionBlock (
- PDESCRIPTION_HEADER Table,
- PACPI_OBJECT Handle
- )
- /*++
- Routine Description:
- This routine loads an ACPI definition block, which contains a standard
- table description header followed by a block of AML. The AML will be loaded
- into the namespace.
- Arguments:
- Table - Supplies a pointer to the table containing the definition block.
- This table should probably only be the DSDT or an SSDT.
- Handle - Supplies an optional pointer to the handle associated with this
- definition block.
- Return Value:
- Status code.
- --*/
- {
- ULONG AmlSize;
- PACPI_LOADED_DEFINITION_BLOCK CurrentBlock;
- PLIST_ENTRY CurrentEntry;
- PAML_EXECUTION_CONTEXT ExecutionContext;
- ULONG ExecutionOptions;
- BOOL IntegerWidthIs32;
- PACPI_LOADED_DEFINITION_BLOCK LoadedBlock;
- BOOL Match;
- PSTR Name;
- KSTATUS Status;
- //
- // First look to see if this table has already been loaded. Don't double
- // load tables.
- //
- CurrentEntry = AcpiLoadedDefinitionBlockList.Next;
- while (CurrentEntry != &AcpiLoadedDefinitionBlockList) {
- CurrentBlock = LIST_VALUE(CurrentEntry,
- ACPI_LOADED_DEFINITION_BLOCK,
- ListEntry);
- CurrentEntry = CurrentEntry->Next;
- if ((CurrentBlock->Code->OemTableId == Table->OemTableId) &&
- (CurrentBlock->Code->Length == Table->Length)) {
- Match = RtlCompareMemory(Table, CurrentBlock->Code, Table->Length);
- if (Match != FALSE) {
- return STATUS_SUCCESS;
- }
- }
- }
- //
- // Create an execution context. Before ACPI 2.0, integers were 32-bits wide.
- //
- IntegerWidthIs32 = FALSE;
- ExecutionContext = NULL;
- LoadedBlock = NULL;
- ExecutionOptions = AML_EXECUTION_OPTION_RUN;
- if (Table->Revision < 2) {
- IntegerWidthIs32 = TRUE;
- }
- AmlSize = Table->Length - sizeof(DESCRIPTION_HEADER);
- ExecutionContext = AcpipCreateAmlExecutionContext(ExecutionOptions);
- if (ExecutionContext == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto LoadDefinitionBlockEnd;
- }
- LoadedBlock = AcpipAllocateMemory(sizeof(ACPI_LOADED_DEFINITION_BLOCK));
- if (LoadedBlock == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto LoadDefinitionBlockEnd;
- }
- RtlZeroMemory(LoadedBlock, sizeof(ACPI_LOADED_DEFINITION_BLOCK));
- INITIALIZE_LIST_HEAD(&(LoadedBlock->ObjectList));
- LoadedBlock->Code = Table;
- if (Handle != NULL) {
- AcpipObjectAddReference(Handle);
- LoadedBlock->HandleObject = Handle;
- }
- INSERT_BEFORE(&(LoadedBlock->ListEntry), &AcpiLoadedDefinitionBlockList);
- //
- // Push a default method context onto the execution context that spans the
- // entire block being loaded.
- //
- Status = AcpipPushMethodOnExecutionContext(ExecutionContext,
- NULL,
- NULL,
- IntegerWidthIs32,
- Table + 1,
- AmlSize,
- 0,
- NULL);
- if (!KSUCCESS(Status)) {
- goto LoadDefinitionBlockEnd;
- }
- ExecutionContext->DestructorListHead = &(LoadedBlock->ObjectList);
- if (ExecutionContext->PrintStatements != FALSE) {
- Name = (PSTR)&(Table->Signature);
- RtlDebugPrint("Loading %c%c%c%c\n", Name[0], Name[1], Name[2], Name[3]);
- }
- Status = AcpipExecuteAml(ExecutionContext);
- if (!KSUCCESS(Status)) {
- goto LoadDefinitionBlockEnd;
- }
- //
- // Run any _INI methods.
- //
- Status = AcpipRunInitializationMethods(NULL);
- if (!KSUCCESS(Status)) {
- goto LoadDefinitionBlockEnd;
- }
- LoadDefinitionBlockEnd:
- if (ExecutionContext != NULL) {
- AcpipDestroyAmlExecutionContext(ExecutionContext);
- }
- if (!KSUCCESS(Status)) {
- if (LoadedBlock != NULL) {
- AcpiUnloadDefinitionBlock(Handle);
- }
- }
- return Status;
- }
- VOID
- AcpiUnloadDefinitionBlock (
- PACPI_OBJECT Handle
- )
- /*++
- Routine Description:
- This routine unloads all ACPI definition blocks loaded under the given
- handle.
- Arguments:
- Handle - Supplies the handle to unload blocks based on. If NULL is
- supplied, then all blocks will be unloaded.
- Return Value:
- None.
- --*/
- {
- PLIST_ENTRY CurrentEntry;
- PACPI_LOADED_DEFINITION_BLOCK LoadedBlock;
- PACPI_OBJECT Object;
- CurrentEntry = AcpiLoadedDefinitionBlockList.Next;
- while (CurrentEntry != &AcpiLoadedDefinitionBlockList) {
- LoadedBlock = LIST_VALUE(CurrentEntry,
- ACPI_LOADED_DEFINITION_BLOCK,
- ListEntry);
- CurrentEntry = CurrentEntry->Next;
- if ((Handle == NULL) || (LoadedBlock->HandleObject == Handle)) {
- LIST_REMOVE(&(LoadedBlock->ListEntry));
- if (LoadedBlock->HandleObject != NULL) {
- AcpipObjectReleaseReference(LoadedBlock->HandleObject);
- }
- //
- // Destroy all the namespace objects created by this definition
- // block.
- //
- while (!LIST_EMPTY(&(LoadedBlock->ObjectList))) {
- Object = LIST_VALUE(LoadedBlock->ObjectList.Next,
- ACPI_OBJECT,
- DestructorListEntry);
- LIST_REMOVE(&(Object->DestructorListEntry));
- Object->DestructorListEntry.Next = NULL;
- AcpipObjectReleaseReference(Object);
- }
- //
- // Free the table as well if this came with a handle. The main
- // DSDT and SSDTs do not have handles, but every AML Load
- // instruction does.
- //
- if (LoadedBlock->HandleObject != NULL) {
- AcpipFreeMemory(LoadedBlock->Code);
- }
- AcpipFreeMemory(LoadedBlock);
- }
- }
- return;
- }
- KSTATUS
- AcpiExecuteMethod (
- PACPI_OBJECT MethodObject,
- PACPI_OBJECT *Arguments,
- ULONG ArgumentCount,
- ACPI_OBJECT_TYPE ReturnType,
- PACPI_OBJECT *ReturnValue
- )
- /*++
- Routine Description:
- This routine executes an ACPI method.
- Arguments:
- MethodObject - Supplies a pointer to the method object. If this object
- is not of type method, then the return value will be set
- directly to this object (and the reference count incremented).
- Arguments - Supplies a pointer to an array of arguments to pass to the
- method. This parameter is optional if the method takes no parameters.
- ArgumentCount - Supplies the number of arguments in the argument array.
- ReturnType - Supplies the desired type to convert the return type argument
- to. Set this to AcpiObjectUninitialized to specify that no conversion
- of the return type should occur (I'm feeling lucky mode).
- ReturnValue - Supplies an optional pointer where a pointer to the return
- value object will be returned. The caller must release the reference
- on this memory when finished with it.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT ConvertedReturnObject;
- PAML_EXECUTION_CONTEXT ExecutionContext;
- ULONG ExecutionOptions;
- PSTR Name;
- PACPI_OBJECT ReturnObject;
- KSTATUS Status;
- ASSERT(KeGetRunLevel() == RunLevelLow);
- ExecutionContext = NULL;
- ReturnObject = NULL;
- if (MethodObject->Type != AcpiObjectMethod) {
- ReturnObject = MethodObject;
- AcpipObjectAddReference(MethodObject);
- Status = STATUS_SUCCESS;
- goto ExecuteMethodEnd;
- }
- //
- // Fire up an execution context.
- //
- ExecutionOptions = AML_EXECUTION_OPTION_RUN;
- ExecutionContext = AcpipCreateAmlExecutionContext(ExecutionOptions);
- if (ExecutionContext == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto ExecuteMethodEnd;
- }
- //
- // Push a default method context onto the execution context that spans the
- // entire block being loaded.
- //
- Status = AcpipPushMethodOnExecutionContext(
- ExecutionContext,
- MethodObject,
- MethodObject->U.Method.OsMutex,
- MethodObject->U.Method.IntegerWidthIs32,
- MethodObject->U.Method.AmlCode,
- MethodObject->U.Method.AmlCodeSize,
- ArgumentCount,
- Arguments);
- if (!KSUCCESS(Status)) {
- goto ExecuteMethodEnd;
- }
- if (ExecutionContext->PrintStatements != FALSE) {
- Name = (PSTR)&(MethodObject->Name);
- RtlDebugPrint("Executing %c%c%c%c\n",
- Name[0],
- Name[1],
- Name[2],
- Name[3]);
- }
- Status = AcpipExecuteAml(ExecutionContext);
- if (!KSUCCESS(Status)) {
- goto ExecuteMethodEnd;
- }
- //
- // If a return value is requested, pluck it out of the context list and
- // convert it to the desired object type.
- //
- if (ReturnValue != NULL) {
- ReturnObject = ExecutionContext->ReturnValue;
- if (ReturnObject != NULL) {
- while (ReturnObject->Type == AcpiObjectAlias) {
- ASSERT(ReturnObject->U.Alias.DestinationObject != NULL);
- ReturnObject = ReturnObject->U.Alias.DestinationObject;
- }
- if ((ReturnType != AcpiObjectUninitialized) &&
- (ReturnObject->Type != ReturnType)) {
- ConvertedReturnObject = AcpipConvertObjectType(ExecutionContext,
- ReturnObject,
- ReturnType);
- if (ConvertedReturnObject == NULL) {
- RtlDebugPrint("ACPI: Failed to convert object %x (type %d) "
- "to return type %d.\n",
- ReturnObject,
- ReturnObject->Type,
- ReturnType);
- }
- ReturnObject = ConvertedReturnObject;
- } else {
- AcpipObjectAddReference(ReturnObject);
- }
- }
- }
- ExecuteMethodEnd:
- if (ExecutionContext != NULL) {
- AcpipDestroyAmlExecutionContext(ExecutionContext);
- }
- if (ReturnValue != NULL) {
- *ReturnValue = ReturnObject;
- }
- return Status;
- }
- KSTATUS
- AcpipInitializeAmlInterpreter (
- VOID
- )
- /*++
- Routine Description:
- This routine initializes the ACPI AML interpreter and global namespace.
- Arguments:
- None.
- Return Value:
- Status code.
- --*/
- {
- PACPI_OBJECT Argument;
- ULONGLONG ArgumentValue;
- PDESCRIPTION_HEADER DsdtTable;
- INTERRUPT_MODEL InterruptModel;
- PACPI_OBJECT PicMethod;
- PDESCRIPTION_HEADER SsdtTable;
- KSTATUS Status;
- Argument = NULL;
- INITIALIZE_LIST_HEAD(&AcpiLoadedDefinitionBlockList);
- //
- // Initialize operating system specific support.
- //
- Status = AcpipInitializeOperatingSystemAmlSupport();
- if (!KSUCCESS(Status)) {
- goto InitializeAmlInterpreterEnd;
- }
- //
- // Initialize the global namespace.
- //
- Status = AcpipInitializeNamespace();
- if (!KSUCCESS(Status)) {
- goto InitializeAmlInterpreterEnd;
- }
- //
- // Load the DSDT.
- //
- DsdtTable = AcpiFindTable(DSDT_SIGNATURE, NULL);
- if (DsdtTable != NULL) {
- Status = AcpiLoadDefinitionBlock(DsdtTable, NULL);
- if (!KSUCCESS(Status)) {
- goto InitializeAmlInterpreterEnd;
- }
- }
- //
- // Load all SSDT tables.
- //
- SsdtTable = NULL;
- while (TRUE) {
- SsdtTable = AcpiFindTable(SSDT_SIGNATURE, SsdtTable);
- if (SsdtTable == NULL) {
- break;
- }
- Status = AcpiLoadDefinitionBlock(SsdtTable, NULL);
- if (!KSUCCESS(Status)) {
- goto InitializeAmlInterpreterEnd;
- }
- }
- //
- // Get the current interrupt model.
- //
- InterruptModel = HlGetInterruptModel();
- if (InterruptModel == InterruptModelPic) {
- ArgumentValue = ACPI_INTERRUPT_PIC_MODEL;
- } else if (InterruptModel == InterruptModelApic) {
- ArgumentValue = ACPI_INTERRUPT_APIC_MODEL;
- } else {
- ASSERT(FALSE);
- Status = STATUS_INVALID_CONFIGURATION;
- goto InitializeAmlInterpreterEnd;
- }
- //
- // Attempt to call the \_PIC routine to tell the firmware which interrupt
- // model is in use.
- //
- PicMethod = AcpipFindNamedObject(AcpipGetNamespaceRoot(),
- ACPI_METHOD__PIC);
- if (PicMethod != NULL) {
- Argument = AcpipCreateNamespaceObject(NULL,
- AcpiObjectInteger,
- NULL,
- &ArgumentValue,
- sizeof(ULONGLONG));
- if (Argument == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto InitializeAmlInterpreterEnd;
- }
- Status = AcpiExecuteMethod(PicMethod,
- &Argument,
- 1,
- 0,
- NULL);
- if (!KSUCCESS(Status)) {
- goto InitializeAmlInterpreterEnd;
- }
- }
- InitializeAmlInterpreterEnd:
- if (Argument != NULL) {
- AcpipObjectReleaseReference(Argument);
- }
- if (!KSUCCESS(Status)) {
- //
- // Unload everything.
- //
- AcpiUnloadDefinitionBlock(NULL);
- }
- return Status;
- }
- UCHAR
- AcpipChecksumData (
- PVOID Address,
- ULONG Length
- )
- /*++
- Routine Description:
- This routine sums all of the bytes in a given buffer. In a correctly
- checksummed region, the result should be zero.
- Arguments:
- Address - Supplies the address of the region to checksum.
- Length - Supplies the length of the region, in bytes.
- Return Value:
- Returns the sum of all the bytes in the region.
- --*/
- {
- PBYTE CurrentByte;
- BYTE Sum;
- CurrentByte = Address;
- Sum = 0;
- while (Length != 0) {
- Sum += *CurrentByte;
- CurrentByte += 1;
- Length -= 1;
- }
- return Sum;
- }
- VOID
- AcpipPopExecutingStatements (
- PAML_EXECUTION_CONTEXT Context,
- BOOL PopToWhile,
- BOOL ContinueWhile
- )
- /*++
- Routine Description:
- This routine causes the AML execution context to pop back up, either because
- the method returned or because while within a while statement a break or
- continue was encountered. This routine only pops statements off the stack,
- it does not modify the current offset pointer.
- Arguments:
- Context - Supplies a pointer to the AML execution context.
- PopToWhile - Supplies a boolean that indicates whether the entire function
- should return (FALSE) or whether to pop to the nearest while statement
- (TRUE). For while statements, the caller is still responsible for
- modifying the AML offset.
- ContinueWhile - Supplies a boolean that indicates whether to re-execute
- the while statement (TRUE) or whether to pop it too (FALSE, for a break
- statement). If the previous argument is FALSE, this parameter is
- ignored.
- Return Value:
- None.
- --*/
- {
- PLIST_ENTRY CurrentEntry;
- PAML_STATEMENT Statement;
- //
- // Don't touch the current statement, but pop statements off behind it
- // until the while is reached or bust.
- //
- while (TRUE) {
- CurrentEntry = Context->StatementStackHead.Next->Next;
- if (CurrentEntry == &(Context->StatementStackHead)) {
- ASSERT(PopToWhile == FALSE);
- break;
- }
- Statement = LIST_VALUE(CurrentEntry, AML_STATEMENT, ListEntry);
- //
- // Assert that the statement wasn't evaluating arguments, but is just
- // here to define scope. Something like Increment (Break) isn't allowed.
- //
- ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
- //
- // If this is a while and that's what's being sought, stop (or pop it
- // off too as the last one.)
- //
- if (PopToWhile != FALSE) {
- if (Statement->Type == AmlStatementWhile) {
- if (ContinueWhile == FALSE) {
- LIST_REMOVE(CurrentEntry);
- AcpipDestroyStatement(Statement);
- }
- break;
- }
- } else {
- if (Statement->Type == AmlStatementExecutingMethod) {
- break;
- }
- }
- //
- // Destroy the statement.
- //
- LIST_REMOVE(CurrentEntry);
- AcpipDestroyStatement(Statement);
- ASSERT(Context->IndentationLevel != 0);
- Context->IndentationLevel -= 1;
- }
- return;
- }
- VOID
- AcpipPrintIndentedNewLine (
- PAML_EXECUTION_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine prints a newline and then a number of space characters
- corresponding to the current indentation level.
- Arguments:
- Context - Supplies a pointer to the AML execution context.
- Return Value:
- None.
- --*/
- {
- ULONG SpaceIndex;
- if (Context->PrintStatements == FALSE) {
- return;
- }
- ASSERT(Context->IndentationLevel < 1000);
- RtlDebugPrint("\n");
- for (SpaceIndex = 0;
- SpaceIndex < Context->IndentationLevel;
- SpaceIndex += 1) {
- RtlDebugPrint(" ");
- }
- return;
- }
- KSTATUS
- AcpipPushMethodOnExecutionContext (
- PAML_EXECUTION_CONTEXT Context,
- PACPI_OBJECT Scope,
- PVOID MethodMutex,
- BOOL IntegerWidthIs32,
- PVOID AmlCode,
- ULONG AmlCodeSize,
- ULONG ArgumentCount,
- PACPI_OBJECT *Arguments
- )
- /*++
- Routine Description:
- This routine pushes a control method onto the given AML execution context,
- causing it to be the next thing to run when the execution context is
- evaluated.
- Arguments:
- Context - Supplies a pointer to the AML execution context to push the
- method onto.
- Scope - Supplies a pointer to the ACPI object to put as the starting scope.
- If NULL is supplied, the namespace root will be used as the default
- scope.
- MethodMutex - Supplies an optional pointer to the mutex to acquire in
- conjunction with executing this serialized method.
- IntegerWidthIs32 - Supplies a boolean indicating if integers should be
- treated as 32-bit values or 64-bit values.
- AmlCode - Supplies a pointer to the first byte of the method.
- AmlCodeSize - Supplies the size of the method, in bytes.
- ArgumentCount - Supplies the number of arguments to pass to the routine.
- Valid values are 0 to 7.
- Arguments - Supplies an array of pointers to ACPI objects representing the
- method arguments. The number of elements in this array is defined by
- the argument count parameter. If that parameter is non-zero, this
- parameter is required.
- Return Value:
- Status code indicating whether the method was successfully pushed onto the
- execution context.
- --*/
- {
- ULONG ArgumentIndex;
- PAML_METHOD_EXECUTION_CONTEXT NewMethod;
- BOOL Result;
- KSTATUS Status;
- //
- // Allocate space for the new method.
- //
- NewMethod = AcpipAllocateMemory(sizeof(AML_METHOD_EXECUTION_CONTEXT));
- if (NewMethod == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto PushMethodOnExecutionContextEnd;
- }
- RtlZeroMemory(NewMethod, sizeof(AML_METHOD_EXECUTION_CONTEXT));
- //
- // Initialize the method context.
- //
- NewMethod->CallingMethodContext = Context->CurrentMethod;
- NewMethod->MethodMutex = MethodMutex;
- NewMethod->IntegerWidthIs32 = IntegerWidthIs32;
- INITIALIZE_LIST_HEAD(&(NewMethod->CreatedObjectsListHead));
- NewMethod->SavedAmlCode = Context->AmlCode;
- NewMethod->SavedAmlCodeSize = Context->AmlCodeSize;
- NewMethod->SavedCurrentOffset = Context->CurrentOffset;
- NewMethod->SavedIndentationLevel = Context->IndentationLevel;
- NewMethod->SavedCurrentScope = Context->CurrentScope;
- if (ArgumentCount != 0) {
- for (ArgumentIndex = 0;
- ArgumentIndex < ArgumentCount;
- ArgumentIndex += 1) {
- NewMethod->Argument[ArgumentIndex] = Arguments[ArgumentIndex];
- AcpipObjectAddReference(NewMethod->Argument[ArgumentIndex]);
- }
- }
- //
- // Acquire the method mutex if there is one.
- //
- if (MethodMutex != NULL) {
- Result = AcpipAcquireMutex(Context,
- MethodMutex,
- ACPI_MUTEX_WAIT_INDEFINITELY);
- ASSERT(Result != FALSE);
- }
- //
- // Set this context as the current one.
- //
- Context->CurrentMethod = NewMethod;
- Context->AmlCode = AmlCode;
- Context->AmlCodeSize = AmlCodeSize;
- Context->CurrentOffset = 0;
- if (Scope == NULL) {
- Scope = AcpipGetNamespaceRoot();
- }
- Context->CurrentScope = Scope;
- Status = STATUS_SUCCESS;
- PushMethodOnExecutionContextEnd:
- return Status;
- }
- VOID
- AcpipPopCurrentMethodContext (
- PAML_EXECUTION_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine pops the current method execution context off of the AML
- execution context, releasing all its associated objects and freeing the
- method context itself.
- Arguments:
- Context - Supplies a pointer to an initialized AML execution context.
- Return Value:
- None.
- --*/
- {
- PLIST_ENTRY CurrentEntry;
- ULONG Index;
- PAML_METHOD_EXECUTION_CONTEXT Method;
- PACPI_OBJECT Object;
- Method = Context->CurrentMethod;
- if (Method == NULL) {
- return;
- }
- //
- // Delete the previous statement manually here if there was one.
- //
- if (Context->PreviousStatement != NULL) {
- AcpipDestroyStatement(Context->PreviousStatement);
- Context->PreviousStatement = NULL;
- }
- //
- // Destroy all locals.
- //
- for (Index = 0; Index < MAX_AML_LOCAL_COUNT; Index += 1) {
- if (Method->LocalVariable[Index] != NULL) {
- AcpipObjectReleaseReference(Method->LocalVariable[Index]);
- }
- }
- //
- // Destroy all arguments.
- //
- for (Index = 0; Index < MAX_AML_METHOD_ARGUMENT_COUNT; Index += 1) {
- if (Method->Argument[Index] != NULL) {
- AcpipObjectReleaseReference(Method->Argument[Index]);
- }
- }
- //
- // Destroy all objects created during this context.
- //
- CurrentEntry = Method->CreatedObjectsListHead.Next;
- while (CurrentEntry != &(Method->CreatedObjectsListHead)) {
- Object = LIST_VALUE(CurrentEntry,
- ACPI_OBJECT,
- DestructorListEntry);
- CurrentEntry = CurrentEntry->Next;
- //
- // Pull the object off of the destructor list in case decrementing its
- // reference count does NOT kill it. That would be bad because when it
- // did finally get destroyed, it would follow a probably freed
- // destructor list entry pointer.
- //
- LIST_REMOVE(&(Object->DestructorListEntry));
- Object->DestructorListEntry.Next = NULL;
- AcpipObjectReleaseReference(Object);
- }
- //
- // Release the implicit method mutex if it was acquired.
- //
- if (Method->MethodMutex != NULL) {
- AcpipReleaseMutex(Context, Method->MethodMutex);
- }
- //
- // Pop the saved values back into the current context.
- //
- Context->CurrentMethod = Method->CallingMethodContext;
- Context->AmlCode = Method->SavedAmlCode;
- Context->AmlCodeSize = Method->SavedAmlCodeSize;
- Context->CurrentOffset = Method->SavedCurrentOffset;
- Context->IndentationLevel = Method->SavedIndentationLevel;
- Context->CurrentScope = Method->SavedCurrentScope;
- //
- // Free this object and return.
- //
- AcpipFreeMemory(Method);
- return;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- PAML_EXECUTION_CONTEXT
- AcpipCreateAmlExecutionContext (
- ULONG Options
- )
- /*++
- Routine Description:
- This routine creates an ACPI execution context.
- Arguments:
- Options - Supplies a bitfield of options that govern the behavior of the
- execution context. See AML_EXECUTION_OPTION_* bitfield definitions.
- Return Value:
- Status code.
- --*/
- {
- PAML_EXECUTION_CONTEXT NewContext;
- //
- // Allocate space for the context.
- //
- NewContext = AcpipAllocateMemory(sizeof(AML_EXECUTION_CONTEXT));
- if (NewContext == NULL) {
- goto CreateAmlExecutionContextEnd;
- }
- RtlZeroMemory(NewContext, sizeof(AML_EXECUTION_CONTEXT));
- //
- // Use the debug options if specified.
- //
- if (AcpiDebugExecutionOptions != 0) {
- RtlDebugPrint("ACPI: Overriding AML execution options from 0x%08x to "
- "0x%08x.\n",
- Options,
- AcpiDebugExecutionOptions);
- Options = AcpiDebugExecutionOptions;
- }
- //
- // Set the options.
- //
- if ((Options & AML_EXECUTION_OPTION_RUN) != 0) {
- NewContext->ExecuteStatements = TRUE;
- }
- if ((Options & AML_EXECUTION_OPTION_PRINT) != 0) {
- NewContext->PrintStatements = TRUE;
- }
- INITIALIZE_LIST_HEAD(&(NewContext->StatementStackHead));
- CreateAmlExecutionContextEnd:
- return NewContext;
- }
- VOID
- AcpipDestroyAmlExecutionContext (
- PAML_EXECUTION_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine destroys an ACPI execution context.
- Arguments:
- Context - Supplies a pointer to the execution context.
- Return Value:
- None.
- --*/
- {
- //
- // Destroy the current method context.
- //
- if (Context->CurrentMethod != NULL) {
- AcpipPopCurrentMethodContext(Context);
- ASSERT(Context->CurrentMethod == NULL);
- }
- //
- // Destroy the return value. The caller had better upped the reference count
- // if it was desired.
- //
- if (Context->ReturnValue != NULL) {
- AcpipObjectReleaseReference(Context->ReturnValue);
- }
- AcpipFreeMemory(Context);
- return;
- }
- KSTATUS
- AcpipExecuteAml (
- PAML_EXECUTION_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine executes a block of ACPI AML.
- Arguments:
- Context - Supplies a pointer to an initialized AML execution context.
- Return Value:
- Status code indicating whether the given block of AML was processed
- successfully.
- --*/
- {
- PLIST_ENTRY CurrentEntry;
- PAML_STATEMENT Statement;
- KSTATUS Status;
- //
- // Loop while not all of the AML has been processed.
- //
- while (TRUE) {
- //
- // Attempt to process the currently executing statement at the top
- // of the stack.
- //
- if (LIST_EMPTY(&(Context->StatementStackHead)) == FALSE) {
- CurrentEntry = Context->StatementStackHead.Next;
- Statement = LIST_VALUE(CurrentEntry, AML_STATEMENT, ListEntry);
- //
- // Attempt to evaluate the statement at the top of the stack.
- //
- Status = AcpipEvaluateStatement(Context, Statement);
- //
- // If there was a previous statement, free it.
- //
- if (Context->PreviousStatement != NULL) {
- AcpipDestroyStatement(Context->PreviousStatement);
- Context->PreviousStatement = NULL;
- }
- //
- // If the statement executed successfully, save it as the previous
- // statement, and pop up the stack to hand it to the parent
- // instruction.
- //
- if (KSUCCESS(Status)) {
- LIST_REMOVE(&(Statement->ListEntry));
- Context->PreviousStatement = Statement;
- //
- // Check to see if the previous statement resolved to a method.
- // If it did, push an executing method statement on to gather
- // arguments and then execute the method.
- //
- if ((Statement->Reduction != NULL) &&
- (Statement->Reduction->Type == AcpiObjectMethod)) {
- Status = AcpipCreateExecutingMethodStatement(Context,
- &Statement);
- if (!KSUCCESS(Status)) {
- goto ExecuteAmlEnd;
- }
- INSERT_AFTER(&(Statement->ListEntry),
- &(Context->StatementStackHead));
- }
- continue;
- }
- //
- // Bail if the error was anything other than "not done yet".
- //
- if (Status != STATUS_MORE_PROCESSING_REQUIRED) {
- ASSERT(FALSE);
- goto ExecuteAmlEnd;
- }
- }
- //
- // If there was a previous statement, free it.
- //
- if (Context->PreviousStatement != NULL) {
- AcpipDestroyStatement(Context->PreviousStatement);
- Context->PreviousStatement = NULL;
- }
- //
- // If this is the end of the AML code, finish.
- //
- if (Context->CurrentOffset == Context->AmlCodeSize) {
- //
- // All statements had better be done.
- //
- ASSERT(LIST_EMPTY(&(Context->StatementStackHead)) != FALSE);
- AcpipPrintIndentedNewLine(Context);
- break;
- }
- //
- // If the list was empty, this is definitely the beginning of a new
- // statement, so print a newline.
- //
- if (LIST_EMPTY(&(Context->StatementStackHead)) != FALSE) {
- AcpipPrintIndentedNewLine(Context);
- }
- //
- // Create the next AML statement and put it on the stack.
- //
- Status = AcpipCreateNextStatement(Context, &Statement);
- if (!KSUCCESS(Status)) {
- goto ExecuteAmlEnd;
- }
- INSERT_AFTER(&(Statement->ListEntry), &(Context->StatementStackHead));
- }
- Status = STATUS_SUCCESS;
- ExecuteAmlEnd:
- return Status;
- }
- KSTATUS
- AcpipCreateNextStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT *NextStatement
- )
- /*++
- Routine Description:
- This routine creates the next AML statement based on the current AML
- execution context.
- Arguments:
- Context - Supplies a pointer to an initialized AML execution context. The
- next statement will be created based on the current execution offset.
- The current offset of the context will be incremented beyond the portion
- of this statement that was successfully parsed.
- NextStatement - Supplies a pointer where a pointer to the next statement
- will be returned. The caller is responsible for freeing this memory.
- Return Value:
- Status code indicating whether a statement was successfully created.
- --*/
- {
- PAML_CREATE_NEXT_STATEMENT_ROUTINE CreateNextStatementRoutine;
- UCHAR FirstByte;
- PAML_STATEMENT Statement;
- KSTATUS Status;
- ASSERT(Context->CurrentOffset < Context->AmlCodeSize);
- //
- // Allocate and initialize the next statement structure.
- //
- Statement = AcpipCreateStatement();
- if (Statement == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto CreateNextStatementEnd;
- }
- //
- // Get the first byte of the opcode, and use that as an index into the table
- // of functions that create the correct statement based on the opcode byte.
- //
- FirstByte = *((PUCHAR)(Context->AmlCode) + Context->CurrentOffset);
- CreateNextStatementRoutine = AcpiCreateStatement[FirstByte];
- Status = CreateNextStatementRoutine(Context, Statement);
- if (!KSUCCESS(Status)) {
- RtlDebugPrint("\nACPI: Failed to create statement. "
- "Status %x, Routine %x, Context %x\n",
- Status,
- CreateNextStatementRoutine,
- Context);
- ASSERT(FALSE);
- goto CreateNextStatementEnd;
- }
- CreateNextStatementEnd:
- if (!KSUCCESS(Status)) {
- if (Statement != NULL) {
- AcpipFreeMemory(Statement);
- Statement = NULL;
- }
- }
- *NextStatement = Statement;
- return Status;
- }
- VOID
- AcpipDestroyStatement (
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine destroys an AML statement object.
- Arguments:
- Statement - Supplies a pointer to the statement to destroy. This routine
- will also free any objects in the arguments list that are not owned
- by a namespace.
- Return Value:
- None.
- --*/
- {
- ULONG ArgumentIndex;
- for (ArgumentIndex = 0;
- ArgumentIndex < Statement->ArgumentsAcquired;
- ArgumentIndex += 1) {
- if (Statement->Argument[ArgumentIndex] != NULL) {
- AcpipObjectReleaseReference(Statement->Argument[ArgumentIndex]);
- }
- }
- if (Statement->Reduction != NULL) {
- AcpipObjectReleaseReference(Statement->Reduction);
- }
- AcpipFreeMemory(Statement);
- return;
- }
- KSTATUS
- AcpipEvaluateStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT Statement
- )
- /*++
- Routine Description:
- This routine attempts to evaluate an AML statement.
- Arguments:
- Context - Supplies a pointer to an initialized AML execution context.
- Statement - Supplies a pointer to the statement to evaluate.
- Return Value:
- Status code.
- --*/
- {
- PAML_EVALUATE_STATEMENT_ROUTINE EvaluateRoutine;
- KSTATUS Status;
- EvaluateRoutine = AcpiEvaluateStatement[Statement->Type];
- ASSERT(EvaluateRoutine != NULL);
- Status = EvaluateRoutine(Context, Statement);
- if ((!KSUCCESS(Status)) && (Status != STATUS_MORE_PROCESSING_REQUIRED)) {
- RtlDebugPrint("\nACPI: Failed to evaluate AML statement. Status: %x, "
- "Context %x, Statement %x\n",
- Status,
- Context,
- Statement);
- ASSERT(FALSE);
- goto EvaluateStatementEnd;
- }
- EvaluateStatementEnd:
- return Status;
- }
- PAML_STATEMENT
- AcpipCreateStatement (
- )
- /*++
- Routine Description:
- This routine allocates and initializes a blank AML statement.
- Arguments:
- None.
- Return Value:
- Returns a pointer to the allocated statement on success.
- NULL on allocation failure.
- --*/
- {
- PAML_STATEMENT Statement;
- //
- // Allocate the next statement structure.
- //
- Statement = AcpipAllocateMemory(sizeof(AML_STATEMENT));
- if (Statement == NULL) {
- goto CreateStatementEnd;
- }
- //
- // Initialize just the essential fields, as this is a very hot path.
- //
- Statement->Reduction = NULL;
- Statement->ArgumentsAcquired = 0;
- CreateStatementEnd:
- return Statement;
- }
- KSTATUS
- AcpipCreateExecutingMethodStatement (
- PAML_EXECUTION_CONTEXT Context,
- PAML_STATEMENT *NextStatement
- )
- /*++
- Routine Description:
- This routine creates an executing method statement.
- Arguments:
- Context - Supplies a pointer to an initialized AML execution context.
- NextStatement - Supplies a pointer where a pointer to the next statement
- will be returned. The caller is responsible for freeing this memory.
- Return Value:
- Status code indicating whether a statement was successfully created.
- --*/
- {
- PAML_STATEMENT Statement;
- KSTATUS Status;
- Statement = AcpipCreateStatement();
- if (Statement == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto CreateExecutingMethodStatementEnd;
- }
- Statement->Type = AmlStatementExecutingMethod;
- Statement->ArgumentsNeeded = 0;
- Statement->ArgumentsAcquired = 0;
- //
- // Set additional data to NULL to indicate the first time the executing
- // method statement is evaluated.
- //
- Statement->AdditionalData = (UINTN)NULL;
- Status = STATUS_SUCCESS;
- //
- // Initialize Additional Data 2 to zero for now. It will eventually hold
- // the original method context.
- //
- Statement->AdditionalData2 = 0;
- CreateExecutingMethodStatementEnd:
- *NextStatement = Statement;
- return Status;
- }
- KSTATUS
- AcpipRunInitializationMethods (
- PACPI_OBJECT RootObject
- )
- /*++
- Routine Description:
- This routine runs immediately after a definition block has been loaded. As
- defined by the ACPI spec, it runs all applicable _INI methods on devices.
- Arguments:
- RootObject - Supplies a pointer to the object to start from. If NULL is
- supplied, the root system bus object \_SB will be used.
- Return Value:
- Status code. Failure means something serious went wrong, not just that some
- device returned a non-functioning status.
- --*/
- {
- PACPI_OBJECT CurrentObject;
- PACPI_OBJECT PreviousObject;
- PACPI_OBJECT PreviousSibling;
- KSTATUS Status;
- BOOL TraverseDown;
- if (RootObject == NULL) {
- RootObject = AcpipGetSystemBusRoot();
- }
- CurrentObject = RootObject;
- PreviousObject = CurrentObject->Parent;
- while (CurrentObject != NULL) {
- //
- // If this is the first time the node is being visited (via parent or
- // sibling, but not child), then process it.
- //
- PreviousSibling = LIST_VALUE(CurrentObject->SiblingListEntry.Previous,
- ACPI_OBJECT,
- SiblingListEntry);
- if ((PreviousObject == CurrentObject->Parent) ||
- ((CurrentObject->SiblingListEntry.Previous != NULL) &&
- (PreviousObject == PreviousSibling))) {
- TraverseDown = TRUE;
- if (CurrentObject->Type == AcpiObjectDevice) {
- Status = AcpipRunDeviceInitialization(CurrentObject,
- &TraverseDown);
- if (!KSUCCESS(Status)) {
- goto RunInitializationMethodsEnd;
- }
- }
- //
- // Move to the first child if eligible.
- //
- PreviousObject = CurrentObject;
- if ((TraverseDown != FALSE) &&
- (LIST_EMPTY(&(CurrentObject->ChildListHead)) == FALSE)) {
- CurrentObject = LIST_VALUE(CurrentObject->ChildListHead.Next,
- ACPI_OBJECT,
- SiblingListEntry);
- //
- // Move to the next sibling if possible.
- //
- } else if ((CurrentObject != RootObject) &&
- (CurrentObject->SiblingListEntry.Next !=
- &(CurrentObject->Parent->ChildListHead))) {
- CurrentObject = LIST_VALUE(CurrentObject->SiblingListEntry.Next,
- ACPI_OBJECT,
- SiblingListEntry);
- //
- // There are no children and this is the last sibling, move up to
- // the parent.
- //
- } else {
- //
- // This case only gets hit if the root is the only node in the
- // tree.
- //
- if (CurrentObject == RootObject) {
- CurrentObject = NULL;
- } else {
- CurrentObject = CurrentObject->Parent;
- }
- }
- //
- // If the node is popping up from the previous, attempt to move to
- // the next sibling, or up the tree.
- //
- } else {
- PreviousObject = CurrentObject;
- if (CurrentObject == RootObject) {
- CurrentObject = NULL;
- } else if (CurrentObject->SiblingListEntry.Next !=
- &(CurrentObject->Parent->ChildListHead)) {
- CurrentObject = LIST_VALUE(CurrentObject->SiblingListEntry.Next,
- ACPI_OBJECT,
- SiblingListEntry);
- } else {
- CurrentObject = CurrentObject->Parent;
- }
- }
- }
- Status = STATUS_SUCCESS;
- RunInitializationMethodsEnd:
- return Status;
- }
- KSTATUS
- AcpipRunDeviceInitialization (
- PACPI_OBJECT Device,
- PBOOL TraverseDown
- )
- /*++
- Routine Description:
- This routine runs the _INI initialization method on a device, if it exists.
- Arguments:
- Device - Supplies a pointer to the device to initialize.
- TraverseDown - Supplies a pointer where a boolean will be returned
- indicating whether or not any of the device's children should be
- initialized.
- Return Value:
- Status code. Failure means something serious went wrong, not just that the
- device returned a non-functioning status.
- --*/
- {
- ULONG DeviceStatus;
- BOOL EvaluateChildren;
- PACPI_OBJECT InitializationMethod;
- KSTATUS Status;
- ASSERT(Device->Type == AcpiObjectDevice);
- DeviceStatus = ACPI_DEFAULT_DEVICE_STATUS;
- EvaluateChildren = TRUE;
- Status = AcpipGetDeviceStatus(Device, &DeviceStatus);
- if (!KSUCCESS(Status)) {
- goto RunDeviceInitializationEnd;
- }
- //
- // Do not evaluate children if the device is neither present nor functional.
- //
- if (((DeviceStatus & ACPI_DEVICE_STATUS_FUNCTIONING_PROPERLY) == 0) &&
- ((DeviceStatus & ACPI_DEVICE_STATUS_PRESENT) == 0)) {
- EvaluateChildren = FALSE;
- }
- //
- // If the device is not present, do not run the _INI method.
- //
- if ((DeviceStatus & ACPI_DEVICE_STATUS_PRESENT) == 0) {
- goto RunDeviceInitializationEnd;
- }
- InitializationMethod = AcpipFindNamedObject(Device, ACPI_METHOD__INI);
- if (InitializationMethod == NULL) {
- goto RunDeviceInitializationEnd;
- }
- Status = AcpiExecuteMethod(InitializationMethod, NULL, 0, 0, NULL);
- if (!KSUCCESS(Status)) {
- goto RunDeviceInitializationEnd;
- }
- RunDeviceInitializationEnd:
- *TraverseDown = EvaluateChildren;
- return Status;
- }
|