aml.c 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881
  1. /*++
  2. Copyright (c) 2012 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. aml.c
  5. Abstract:
  6. This module implements the ACPI AML interpreter.
  7. Author:
  8. Evan Green 13-Nov-2012
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/kernel/driver.h>
  16. #include "acpip.h"
  17. #include "amlos.h"
  18. #include "amlops.h"
  19. #include "namespce.h"
  20. //
  21. // ---------------------------------------------------------------- Definitions
  22. //
  23. //
  24. // Define AML execution options.
  25. //
  26. //
  27. // Set this bit to actually execute the given definition block.
  28. //
  29. #define AML_EXECUTION_OPTION_RUN 0x00000001
  30. //
  31. // Set this bit to print out the definition block to the debugger.
  32. //
  33. #define AML_EXECUTION_OPTION_PRINT 0x00000002
  34. //
  35. // ------------------------------------------------------ Data Type Definitions
  36. //
  37. /*++
  38. Structure Description:
  39. This structure stores information about a loaded SSDT table.
  40. Members:
  41. ListEntry - Stores pointers to the next and previous secondary definition
  42. tables.
  43. HandleObject - Stores the optional handle associated with this definition
  44. block.
  45. ObjectList - Stores the head of the list of namespace objects to destroy if
  46. this definition block is unloaded. The objects on this list will be
  47. ACPI objects, and the list entry is the destructor list entry.
  48. Code - Stores the AML code for this definition block.
  49. --*/
  50. typedef struct _ACPI_LOADED_DEFINITION_BLOCK {
  51. LIST_ENTRY ListEntry;
  52. PACPI_OBJECT HandleObject;
  53. LIST_ENTRY ObjectList;
  54. PDESCRIPTION_HEADER Code;
  55. } ACPI_LOADED_DEFINITION_BLOCK, *PACPI_LOADED_DEFINITION_BLOCK;
  56. //
  57. // ----------------------------------------------- Internal Function Prototypes
  58. //
  59. PAML_EXECUTION_CONTEXT
  60. AcpipCreateAmlExecutionContext (
  61. ULONG Options
  62. );
  63. VOID
  64. AcpipDestroyAmlExecutionContext (
  65. PAML_EXECUTION_CONTEXT Context
  66. );
  67. KSTATUS
  68. AcpipExecuteAml (
  69. PAML_EXECUTION_CONTEXT Context
  70. );
  71. KSTATUS
  72. AcpipCreateNextStatement (
  73. PAML_EXECUTION_CONTEXT Context,
  74. PAML_STATEMENT *NextStatement
  75. );
  76. VOID
  77. AcpipDestroyStatement (
  78. PAML_STATEMENT Statement
  79. );
  80. KSTATUS
  81. AcpipEvaluateStatement (
  82. PAML_EXECUTION_CONTEXT Context,
  83. PAML_STATEMENT Statement
  84. );
  85. PAML_STATEMENT
  86. AcpipCreateStatement (
  87. );
  88. KSTATUS
  89. AcpipCreateExecutingMethodStatement (
  90. PAML_EXECUTION_CONTEXT Context,
  91. PAML_STATEMENT *NextStatement
  92. );
  93. KSTATUS
  94. AcpipRunInitializationMethods (
  95. PACPI_OBJECT RootObject
  96. );
  97. KSTATUS
  98. AcpipRunDeviceInitialization (
  99. PACPI_OBJECT Device,
  100. PBOOL TraverseDown
  101. );
  102. //
  103. // -------------------------------------------------------------------- Globals
  104. //
  105. //
  106. // Define a value that can be set from the debugger to change the behavior
  107. // of the AML interpreter. For example, it can be set to print out the
  108. // statements it's executing. See AML_EXECUTION_OPTION_* definitions.
  109. //
  110. ULONG AcpiDebugExecutionOptions = 0x0;
  111. //
  112. // Store the list of SSDT definition blocks.
  113. //
  114. LIST_ENTRY AcpiLoadedDefinitionBlockList;
  115. //
  116. // ------------------------------------------------------------------ Functions
  117. //
  118. KSTATUS
  119. AcpiLoadDefinitionBlock (
  120. PDESCRIPTION_HEADER Table,
  121. PACPI_OBJECT Handle
  122. )
  123. /*++
  124. Routine Description:
  125. This routine loads an ACPI definition block, which contains a standard
  126. table description header followed by a block of AML. The AML will be loaded
  127. into the namespace.
  128. Arguments:
  129. Table - Supplies a pointer to the table containing the definition block.
  130. This table should probably only be the DSDT or an SSDT.
  131. Handle - Supplies an optional pointer to the handle associated with this
  132. definition block.
  133. Return Value:
  134. Status code.
  135. --*/
  136. {
  137. ULONG AmlSize;
  138. PACPI_LOADED_DEFINITION_BLOCK CurrentBlock;
  139. PLIST_ENTRY CurrentEntry;
  140. PAML_EXECUTION_CONTEXT ExecutionContext;
  141. ULONG ExecutionOptions;
  142. BOOL IntegerWidthIs32;
  143. PACPI_LOADED_DEFINITION_BLOCK LoadedBlock;
  144. BOOL Match;
  145. PSTR Name;
  146. KSTATUS Status;
  147. //
  148. // First look to see if this table has already been loaded. Don't double
  149. // load tables.
  150. //
  151. CurrentEntry = AcpiLoadedDefinitionBlockList.Next;
  152. while (CurrentEntry != &AcpiLoadedDefinitionBlockList) {
  153. CurrentBlock = LIST_VALUE(CurrentEntry,
  154. ACPI_LOADED_DEFINITION_BLOCK,
  155. ListEntry);
  156. CurrentEntry = CurrentEntry->Next;
  157. if ((CurrentBlock->Code->OemTableId == Table->OemTableId) &&
  158. (CurrentBlock->Code->Length == Table->Length)) {
  159. Match = RtlCompareMemory(Table, CurrentBlock->Code, Table->Length);
  160. if (Match != FALSE) {
  161. return STATUS_SUCCESS;
  162. }
  163. }
  164. }
  165. //
  166. // Create an execution context. Before ACPI 2.0, integers were 32-bits wide.
  167. //
  168. IntegerWidthIs32 = FALSE;
  169. ExecutionContext = NULL;
  170. LoadedBlock = NULL;
  171. ExecutionOptions = AML_EXECUTION_OPTION_RUN;
  172. if (Table->Revision < 2) {
  173. IntegerWidthIs32 = TRUE;
  174. }
  175. AmlSize = Table->Length - sizeof(DESCRIPTION_HEADER);
  176. ExecutionContext = AcpipCreateAmlExecutionContext(ExecutionOptions);
  177. if (ExecutionContext == NULL) {
  178. Status = STATUS_INSUFFICIENT_RESOURCES;
  179. goto LoadDefinitionBlockEnd;
  180. }
  181. LoadedBlock = AcpipAllocateMemory(sizeof(ACPI_LOADED_DEFINITION_BLOCK));
  182. if (LoadedBlock == NULL) {
  183. Status = STATUS_INSUFFICIENT_RESOURCES;
  184. goto LoadDefinitionBlockEnd;
  185. }
  186. RtlZeroMemory(LoadedBlock, sizeof(ACPI_LOADED_DEFINITION_BLOCK));
  187. INITIALIZE_LIST_HEAD(&(LoadedBlock->ObjectList));
  188. LoadedBlock->Code = Table;
  189. if (Handle != NULL) {
  190. AcpipObjectAddReference(Handle);
  191. LoadedBlock->HandleObject = Handle;
  192. }
  193. INSERT_BEFORE(&(LoadedBlock->ListEntry), &AcpiLoadedDefinitionBlockList);
  194. //
  195. // Push a default method context onto the execution context that spans the
  196. // entire block being loaded.
  197. //
  198. Status = AcpipPushMethodOnExecutionContext(ExecutionContext,
  199. NULL,
  200. NULL,
  201. IntegerWidthIs32,
  202. Table + 1,
  203. AmlSize,
  204. 0,
  205. NULL);
  206. if (!KSUCCESS(Status)) {
  207. goto LoadDefinitionBlockEnd;
  208. }
  209. ExecutionContext->DestructorListHead = &(LoadedBlock->ObjectList);
  210. if (ExecutionContext->PrintStatements != FALSE) {
  211. Name = (PSTR)&(Table->Signature);
  212. RtlDebugPrint("Loading %c%c%c%c\n", Name[0], Name[1], Name[2], Name[3]);
  213. }
  214. Status = AcpipExecuteAml(ExecutionContext);
  215. if (!KSUCCESS(Status)) {
  216. goto LoadDefinitionBlockEnd;
  217. }
  218. //
  219. // Run any _INI methods.
  220. //
  221. Status = AcpipRunInitializationMethods(NULL);
  222. if (!KSUCCESS(Status)) {
  223. goto LoadDefinitionBlockEnd;
  224. }
  225. LoadDefinitionBlockEnd:
  226. if (ExecutionContext != NULL) {
  227. AcpipDestroyAmlExecutionContext(ExecutionContext);
  228. }
  229. if (!KSUCCESS(Status)) {
  230. if (LoadedBlock != NULL) {
  231. AcpiUnloadDefinitionBlock(Handle);
  232. }
  233. }
  234. return Status;
  235. }
  236. VOID
  237. AcpiUnloadDefinitionBlock (
  238. PACPI_OBJECT Handle
  239. )
  240. /*++
  241. Routine Description:
  242. This routine unloads all ACPI definition blocks loaded under the given
  243. handle.
  244. Arguments:
  245. Handle - Supplies the handle to unload blocks based on. If NULL is
  246. supplied, then all blocks will be unloaded.
  247. Return Value:
  248. None.
  249. --*/
  250. {
  251. PLIST_ENTRY CurrentEntry;
  252. PACPI_LOADED_DEFINITION_BLOCK LoadedBlock;
  253. PACPI_OBJECT Object;
  254. CurrentEntry = AcpiLoadedDefinitionBlockList.Next;
  255. while (CurrentEntry != &AcpiLoadedDefinitionBlockList) {
  256. LoadedBlock = LIST_VALUE(CurrentEntry,
  257. ACPI_LOADED_DEFINITION_BLOCK,
  258. ListEntry);
  259. CurrentEntry = CurrentEntry->Next;
  260. if ((Handle == NULL) || (LoadedBlock->HandleObject == Handle)) {
  261. LIST_REMOVE(&(LoadedBlock->ListEntry));
  262. if (LoadedBlock->HandleObject != NULL) {
  263. AcpipObjectReleaseReference(LoadedBlock->HandleObject);
  264. }
  265. //
  266. // Destroy all the namespace objects created by this definition
  267. // block.
  268. //
  269. while (!LIST_EMPTY(&(LoadedBlock->ObjectList))) {
  270. Object = LIST_VALUE(LoadedBlock->ObjectList.Next,
  271. ACPI_OBJECT,
  272. DestructorListEntry);
  273. LIST_REMOVE(&(Object->DestructorListEntry));
  274. Object->DestructorListEntry.Next = NULL;
  275. AcpipObjectReleaseReference(Object);
  276. }
  277. //
  278. // Free the table as well if this came with a handle. The main
  279. // DSDT and SSDTs do not have handles, but every AML Load
  280. // instruction does.
  281. //
  282. if (LoadedBlock->HandleObject != NULL) {
  283. AcpipFreeMemory(LoadedBlock->Code);
  284. }
  285. AcpipFreeMemory(LoadedBlock);
  286. }
  287. }
  288. return;
  289. }
  290. KSTATUS
  291. AcpiExecuteMethod (
  292. PACPI_OBJECT MethodObject,
  293. PACPI_OBJECT *Arguments,
  294. ULONG ArgumentCount,
  295. ACPI_OBJECT_TYPE ReturnType,
  296. PACPI_OBJECT *ReturnValue
  297. )
  298. /*++
  299. Routine Description:
  300. This routine executes an ACPI method.
  301. Arguments:
  302. MethodObject - Supplies a pointer to the method object. If this object
  303. is not of type method, then the return value will be set
  304. directly to this object (and the reference count incremented).
  305. Arguments - Supplies a pointer to an array of arguments to pass to the
  306. method. This parameter is optional if the method takes no parameters.
  307. ArgumentCount - Supplies the number of arguments in the argument array.
  308. ReturnType - Supplies the desired type to convert the return type argument
  309. to. Set this to AcpiObjectUninitialized to specify that no conversion
  310. of the return type should occur (I'm feeling lucky mode).
  311. ReturnValue - Supplies an optional pointer where a pointer to the return
  312. value object will be returned. The caller must release the reference
  313. on this memory when finished with it.
  314. Return Value:
  315. Status code.
  316. --*/
  317. {
  318. PACPI_OBJECT ConvertedReturnObject;
  319. PAML_EXECUTION_CONTEXT ExecutionContext;
  320. ULONG ExecutionOptions;
  321. PSTR Name;
  322. PACPI_OBJECT ReturnObject;
  323. KSTATUS Status;
  324. ASSERT(KeGetRunLevel() == RunLevelLow);
  325. ExecutionContext = NULL;
  326. ReturnObject = NULL;
  327. if (MethodObject->Type != AcpiObjectMethod) {
  328. ReturnObject = MethodObject;
  329. AcpipObjectAddReference(MethodObject);
  330. Status = STATUS_SUCCESS;
  331. goto ExecuteMethodEnd;
  332. }
  333. //
  334. // Fire up an execution context.
  335. //
  336. ExecutionOptions = AML_EXECUTION_OPTION_RUN;
  337. ExecutionContext = AcpipCreateAmlExecutionContext(ExecutionOptions);
  338. if (ExecutionContext == NULL) {
  339. Status = STATUS_INSUFFICIENT_RESOURCES;
  340. goto ExecuteMethodEnd;
  341. }
  342. //
  343. // Push a default method context onto the execution context that spans the
  344. // entire block being loaded.
  345. //
  346. Status = AcpipPushMethodOnExecutionContext(
  347. ExecutionContext,
  348. MethodObject,
  349. MethodObject->U.Method.OsMutex,
  350. MethodObject->U.Method.IntegerWidthIs32,
  351. MethodObject->U.Method.AmlCode,
  352. MethodObject->U.Method.AmlCodeSize,
  353. ArgumentCount,
  354. Arguments);
  355. if (!KSUCCESS(Status)) {
  356. goto ExecuteMethodEnd;
  357. }
  358. if (ExecutionContext->PrintStatements != FALSE) {
  359. Name = (PSTR)&(MethodObject->Name);
  360. RtlDebugPrint("Executing %c%c%c%c\n",
  361. Name[0],
  362. Name[1],
  363. Name[2],
  364. Name[3]);
  365. }
  366. Status = AcpipExecuteAml(ExecutionContext);
  367. if (!KSUCCESS(Status)) {
  368. goto ExecuteMethodEnd;
  369. }
  370. //
  371. // If a return value is requested, pluck it out of the context list and
  372. // convert it to the desired object type.
  373. //
  374. if (ReturnValue != NULL) {
  375. ReturnObject = ExecutionContext->ReturnValue;
  376. if (ReturnObject != NULL) {
  377. while (ReturnObject->Type == AcpiObjectAlias) {
  378. ASSERT(ReturnObject->U.Alias.DestinationObject != NULL);
  379. ReturnObject = ReturnObject->U.Alias.DestinationObject;
  380. }
  381. if ((ReturnType != AcpiObjectUninitialized) &&
  382. (ReturnObject->Type != ReturnType)) {
  383. ConvertedReturnObject = AcpipConvertObjectType(ExecutionContext,
  384. ReturnObject,
  385. ReturnType);
  386. if (ConvertedReturnObject == NULL) {
  387. RtlDebugPrint("ACPI: Failed to convert object %x (type %d) "
  388. "to return type %d.\n",
  389. ReturnObject,
  390. ReturnObject->Type,
  391. ReturnType);
  392. }
  393. ReturnObject = ConvertedReturnObject;
  394. } else {
  395. AcpipObjectAddReference(ReturnObject);
  396. }
  397. }
  398. }
  399. ExecuteMethodEnd:
  400. if (ExecutionContext != NULL) {
  401. AcpipDestroyAmlExecutionContext(ExecutionContext);
  402. }
  403. if (ReturnValue != NULL) {
  404. *ReturnValue = ReturnObject;
  405. }
  406. return Status;
  407. }
  408. KSTATUS
  409. AcpipInitializeAmlInterpreter (
  410. VOID
  411. )
  412. /*++
  413. Routine Description:
  414. This routine initializes the ACPI AML interpreter and global namespace.
  415. Arguments:
  416. None.
  417. Return Value:
  418. Status code.
  419. --*/
  420. {
  421. PACPI_OBJECT Argument;
  422. ULONGLONG ArgumentValue;
  423. PDESCRIPTION_HEADER DsdtTable;
  424. INTERRUPT_MODEL InterruptModel;
  425. PACPI_OBJECT PicMethod;
  426. PDESCRIPTION_HEADER SsdtTable;
  427. KSTATUS Status;
  428. Argument = NULL;
  429. INITIALIZE_LIST_HEAD(&AcpiLoadedDefinitionBlockList);
  430. //
  431. // Initialize operating system specific support.
  432. //
  433. Status = AcpipInitializeOperatingSystemAmlSupport();
  434. if (!KSUCCESS(Status)) {
  435. goto InitializeAmlInterpreterEnd;
  436. }
  437. //
  438. // Initialize the global namespace.
  439. //
  440. Status = AcpipInitializeNamespace();
  441. if (!KSUCCESS(Status)) {
  442. goto InitializeAmlInterpreterEnd;
  443. }
  444. //
  445. // Load the DSDT.
  446. //
  447. DsdtTable = AcpiFindTable(DSDT_SIGNATURE, NULL);
  448. if (DsdtTable != NULL) {
  449. Status = AcpiLoadDefinitionBlock(DsdtTable, NULL);
  450. if (!KSUCCESS(Status)) {
  451. goto InitializeAmlInterpreterEnd;
  452. }
  453. }
  454. //
  455. // Load all SSDT tables.
  456. //
  457. SsdtTable = NULL;
  458. while (TRUE) {
  459. SsdtTable = AcpiFindTable(SSDT_SIGNATURE, SsdtTable);
  460. if (SsdtTable == NULL) {
  461. break;
  462. }
  463. Status = AcpiLoadDefinitionBlock(SsdtTable, NULL);
  464. if (!KSUCCESS(Status)) {
  465. goto InitializeAmlInterpreterEnd;
  466. }
  467. }
  468. //
  469. // Get the current interrupt model.
  470. //
  471. InterruptModel = HlGetInterruptModel();
  472. if (InterruptModel == InterruptModelPic) {
  473. ArgumentValue = ACPI_INTERRUPT_PIC_MODEL;
  474. } else if (InterruptModel == InterruptModelApic) {
  475. ArgumentValue = ACPI_INTERRUPT_APIC_MODEL;
  476. } else {
  477. ASSERT(FALSE);
  478. Status = STATUS_INVALID_CONFIGURATION;
  479. goto InitializeAmlInterpreterEnd;
  480. }
  481. //
  482. // Attempt to call the \_PIC routine to tell the firmware which interrupt
  483. // model is in use.
  484. //
  485. PicMethod = AcpipFindNamedObject(AcpipGetNamespaceRoot(),
  486. ACPI_METHOD__PIC);
  487. if (PicMethod != NULL) {
  488. Argument = AcpipCreateNamespaceObject(NULL,
  489. AcpiObjectInteger,
  490. NULL,
  491. &ArgumentValue,
  492. sizeof(ULONGLONG));
  493. if (Argument == NULL) {
  494. Status = STATUS_INSUFFICIENT_RESOURCES;
  495. goto InitializeAmlInterpreterEnd;
  496. }
  497. Status = AcpiExecuteMethod(PicMethod,
  498. &Argument,
  499. 1,
  500. 0,
  501. NULL);
  502. if (!KSUCCESS(Status)) {
  503. goto InitializeAmlInterpreterEnd;
  504. }
  505. }
  506. InitializeAmlInterpreterEnd:
  507. if (Argument != NULL) {
  508. AcpipObjectReleaseReference(Argument);
  509. }
  510. if (!KSUCCESS(Status)) {
  511. //
  512. // Unload everything.
  513. //
  514. AcpiUnloadDefinitionBlock(NULL);
  515. }
  516. return Status;
  517. }
  518. UCHAR
  519. AcpipChecksumData (
  520. PVOID Address,
  521. ULONG Length
  522. )
  523. /*++
  524. Routine Description:
  525. This routine sums all of the bytes in a given buffer. In a correctly
  526. checksummed region, the result should be zero.
  527. Arguments:
  528. Address - Supplies the address of the region to checksum.
  529. Length - Supplies the length of the region, in bytes.
  530. Return Value:
  531. Returns the sum of all the bytes in the region.
  532. --*/
  533. {
  534. PBYTE CurrentByte;
  535. BYTE Sum;
  536. CurrentByte = Address;
  537. Sum = 0;
  538. while (Length != 0) {
  539. Sum += *CurrentByte;
  540. CurrentByte += 1;
  541. Length -= 1;
  542. }
  543. return Sum;
  544. }
  545. VOID
  546. AcpipPopExecutingStatements (
  547. PAML_EXECUTION_CONTEXT Context,
  548. BOOL PopToWhile,
  549. BOOL ContinueWhile
  550. )
  551. /*++
  552. Routine Description:
  553. This routine causes the AML execution context to pop back up, either because
  554. the method returned or because while within a while statement a break or
  555. continue was encountered. This routine only pops statements off the stack,
  556. it does not modify the current offset pointer.
  557. Arguments:
  558. Context - Supplies a pointer to the AML execution context.
  559. PopToWhile - Supplies a boolean that indicates whether the entire function
  560. should return (FALSE) or whether to pop to the nearest while statement
  561. (TRUE). For while statements, the caller is still responsible for
  562. modifying the AML offset.
  563. ContinueWhile - Supplies a boolean that indicates whether to re-execute
  564. the while statement (TRUE) or whether to pop it too (FALSE, for a break
  565. statement). If the previous argument is FALSE, this parameter is
  566. ignored.
  567. Return Value:
  568. None.
  569. --*/
  570. {
  571. PLIST_ENTRY CurrentEntry;
  572. PAML_STATEMENT Statement;
  573. //
  574. // Don't touch the current statement, but pop statements off behind it
  575. // until the while is reached or bust.
  576. //
  577. while (TRUE) {
  578. CurrentEntry = Context->StatementStackHead.Next->Next;
  579. if (CurrentEntry == &(Context->StatementStackHead)) {
  580. ASSERT(PopToWhile == FALSE);
  581. break;
  582. }
  583. Statement = LIST_VALUE(CurrentEntry, AML_STATEMENT, ListEntry);
  584. //
  585. // Assert that the statement wasn't evaluating arguments, but is just
  586. // here to define scope. Something like Increment (Break) isn't allowed.
  587. //
  588. ASSERT(Statement->ArgumentsNeeded == Statement->ArgumentsAcquired);
  589. //
  590. // If this is a while and that's what's being sought, stop (or pop it
  591. // off too as the last one.)
  592. //
  593. if (PopToWhile != FALSE) {
  594. if (Statement->Type == AmlStatementWhile) {
  595. if (ContinueWhile == FALSE) {
  596. LIST_REMOVE(CurrentEntry);
  597. AcpipDestroyStatement(Statement);
  598. }
  599. break;
  600. }
  601. } else {
  602. if (Statement->Type == AmlStatementExecutingMethod) {
  603. break;
  604. }
  605. }
  606. //
  607. // Destroy the statement.
  608. //
  609. LIST_REMOVE(CurrentEntry);
  610. AcpipDestroyStatement(Statement);
  611. ASSERT(Context->IndentationLevel != 0);
  612. Context->IndentationLevel -= 1;
  613. }
  614. return;
  615. }
  616. VOID
  617. AcpipPrintIndentedNewLine (
  618. PAML_EXECUTION_CONTEXT Context
  619. )
  620. /*++
  621. Routine Description:
  622. This routine prints a newline and then a number of space characters
  623. corresponding to the current indentation level.
  624. Arguments:
  625. Context - Supplies a pointer to the AML execution context.
  626. Return Value:
  627. None.
  628. --*/
  629. {
  630. ULONG SpaceIndex;
  631. if (Context->PrintStatements == FALSE) {
  632. return;
  633. }
  634. ASSERT(Context->IndentationLevel < 1000);
  635. RtlDebugPrint("\n");
  636. for (SpaceIndex = 0;
  637. SpaceIndex < Context->IndentationLevel;
  638. SpaceIndex += 1) {
  639. RtlDebugPrint(" ");
  640. }
  641. return;
  642. }
  643. KSTATUS
  644. AcpipPushMethodOnExecutionContext (
  645. PAML_EXECUTION_CONTEXT Context,
  646. PACPI_OBJECT Scope,
  647. PVOID MethodMutex,
  648. BOOL IntegerWidthIs32,
  649. PVOID AmlCode,
  650. ULONG AmlCodeSize,
  651. ULONG ArgumentCount,
  652. PACPI_OBJECT *Arguments
  653. )
  654. /*++
  655. Routine Description:
  656. This routine pushes a control method onto the given AML execution context,
  657. causing it to be the next thing to run when the execution context is
  658. evaluated.
  659. Arguments:
  660. Context - Supplies a pointer to the AML execution context to push the
  661. method onto.
  662. Scope - Supplies a pointer to the ACPI object to put as the starting scope.
  663. If NULL is supplied, the namespace root will be used as the default
  664. scope.
  665. MethodMutex - Supplies an optional pointer to the mutex to acquire in
  666. conjunction with executing this serialized method.
  667. IntegerWidthIs32 - Supplies a boolean indicating if integers should be
  668. treated as 32-bit values or 64-bit values.
  669. AmlCode - Supplies a pointer to the first byte of the method.
  670. AmlCodeSize - Supplies the size of the method, in bytes.
  671. ArgumentCount - Supplies the number of arguments to pass to the routine.
  672. Valid values are 0 to 7.
  673. Arguments - Supplies an array of pointers to ACPI objects representing the
  674. method arguments. The number of elements in this array is defined by
  675. the argument count parameter. If that parameter is non-zero, this
  676. parameter is required.
  677. Return Value:
  678. Status code indicating whether the method was successfully pushed onto the
  679. execution context.
  680. --*/
  681. {
  682. ULONG ArgumentIndex;
  683. PAML_METHOD_EXECUTION_CONTEXT NewMethod;
  684. BOOL Result;
  685. KSTATUS Status;
  686. //
  687. // Allocate space for the new method.
  688. //
  689. NewMethod = AcpipAllocateMemory(sizeof(AML_METHOD_EXECUTION_CONTEXT));
  690. if (NewMethod == NULL) {
  691. Status = STATUS_INSUFFICIENT_RESOURCES;
  692. goto PushMethodOnExecutionContextEnd;
  693. }
  694. RtlZeroMemory(NewMethod, sizeof(AML_METHOD_EXECUTION_CONTEXT));
  695. //
  696. // Initialize the method context.
  697. //
  698. NewMethod->CallingMethodContext = Context->CurrentMethod;
  699. NewMethod->MethodMutex = MethodMutex;
  700. NewMethod->IntegerWidthIs32 = IntegerWidthIs32;
  701. INITIALIZE_LIST_HEAD(&(NewMethod->CreatedObjectsListHead));
  702. NewMethod->SavedAmlCode = Context->AmlCode;
  703. NewMethod->SavedAmlCodeSize = Context->AmlCodeSize;
  704. NewMethod->SavedCurrentOffset = Context->CurrentOffset;
  705. NewMethod->SavedIndentationLevel = Context->IndentationLevel;
  706. NewMethod->SavedCurrentScope = Context->CurrentScope;
  707. if (ArgumentCount != 0) {
  708. for (ArgumentIndex = 0;
  709. ArgumentIndex < ArgumentCount;
  710. ArgumentIndex += 1) {
  711. NewMethod->Argument[ArgumentIndex] = Arguments[ArgumentIndex];
  712. AcpipObjectAddReference(NewMethod->Argument[ArgumentIndex]);
  713. }
  714. }
  715. //
  716. // Acquire the method mutex if there is one.
  717. //
  718. if (MethodMutex != NULL) {
  719. Result = AcpipAcquireMutex(Context,
  720. MethodMutex,
  721. ACPI_MUTEX_WAIT_INDEFINITELY);
  722. ASSERT(Result != FALSE);
  723. }
  724. //
  725. // Set this context as the current one.
  726. //
  727. Context->CurrentMethod = NewMethod;
  728. Context->AmlCode = AmlCode;
  729. Context->AmlCodeSize = AmlCodeSize;
  730. Context->CurrentOffset = 0;
  731. if (Scope == NULL) {
  732. Scope = AcpipGetNamespaceRoot();
  733. }
  734. Context->CurrentScope = Scope;
  735. Status = STATUS_SUCCESS;
  736. PushMethodOnExecutionContextEnd:
  737. return Status;
  738. }
  739. VOID
  740. AcpipPopCurrentMethodContext (
  741. PAML_EXECUTION_CONTEXT Context
  742. )
  743. /*++
  744. Routine Description:
  745. This routine pops the current method execution context off of the AML
  746. execution context, releasing all its associated objects and freeing the
  747. method context itself.
  748. Arguments:
  749. Context - Supplies a pointer to an initialized AML execution context.
  750. Return Value:
  751. None.
  752. --*/
  753. {
  754. PLIST_ENTRY CurrentEntry;
  755. ULONG Index;
  756. PAML_METHOD_EXECUTION_CONTEXT Method;
  757. PACPI_OBJECT Object;
  758. Method = Context->CurrentMethod;
  759. if (Method == NULL) {
  760. return;
  761. }
  762. //
  763. // Delete the previous statement manually here if there was one.
  764. //
  765. if (Context->PreviousStatement != NULL) {
  766. AcpipDestroyStatement(Context->PreviousStatement);
  767. Context->PreviousStatement = NULL;
  768. }
  769. //
  770. // Destroy all locals.
  771. //
  772. for (Index = 0; Index < MAX_AML_LOCAL_COUNT; Index += 1) {
  773. if (Method->LocalVariable[Index] != NULL) {
  774. AcpipObjectReleaseReference(Method->LocalVariable[Index]);
  775. }
  776. }
  777. //
  778. // Destroy all arguments.
  779. //
  780. for (Index = 0; Index < MAX_AML_METHOD_ARGUMENT_COUNT; Index += 1) {
  781. if (Method->Argument[Index] != NULL) {
  782. AcpipObjectReleaseReference(Method->Argument[Index]);
  783. }
  784. }
  785. //
  786. // Destroy all objects created during this context.
  787. //
  788. CurrentEntry = Method->CreatedObjectsListHead.Next;
  789. while (CurrentEntry != &(Method->CreatedObjectsListHead)) {
  790. Object = LIST_VALUE(CurrentEntry,
  791. ACPI_OBJECT,
  792. DestructorListEntry);
  793. CurrentEntry = CurrentEntry->Next;
  794. //
  795. // Pull the object off of the destructor list in case decrementing its
  796. // reference count does NOT kill it. That would be bad because when it
  797. // did finally get destroyed, it would follow a probably freed
  798. // destructor list entry pointer.
  799. //
  800. LIST_REMOVE(&(Object->DestructorListEntry));
  801. Object->DestructorListEntry.Next = NULL;
  802. AcpipObjectReleaseReference(Object);
  803. }
  804. //
  805. // Release the implicit method mutex if it was acquired.
  806. //
  807. if (Method->MethodMutex != NULL) {
  808. AcpipReleaseMutex(Context, Method->MethodMutex);
  809. }
  810. //
  811. // Pop the saved values back into the current context.
  812. //
  813. Context->CurrentMethod = Method->CallingMethodContext;
  814. Context->AmlCode = Method->SavedAmlCode;
  815. Context->AmlCodeSize = Method->SavedAmlCodeSize;
  816. Context->CurrentOffset = Method->SavedCurrentOffset;
  817. Context->IndentationLevel = Method->SavedIndentationLevel;
  818. Context->CurrentScope = Method->SavedCurrentScope;
  819. //
  820. // Free this object and return.
  821. //
  822. AcpipFreeMemory(Method);
  823. return;
  824. }
  825. //
  826. // --------------------------------------------------------- Internal Functions
  827. //
  828. PAML_EXECUTION_CONTEXT
  829. AcpipCreateAmlExecutionContext (
  830. ULONG Options
  831. )
  832. /*++
  833. Routine Description:
  834. This routine creates an ACPI execution context.
  835. Arguments:
  836. Options - Supplies a bitfield of options that govern the behavior of the
  837. execution context. See AML_EXECUTION_OPTION_* bitfield definitions.
  838. Return Value:
  839. Status code.
  840. --*/
  841. {
  842. PAML_EXECUTION_CONTEXT NewContext;
  843. //
  844. // Allocate space for the context.
  845. //
  846. NewContext = AcpipAllocateMemory(sizeof(AML_EXECUTION_CONTEXT));
  847. if (NewContext == NULL) {
  848. goto CreateAmlExecutionContextEnd;
  849. }
  850. RtlZeroMemory(NewContext, sizeof(AML_EXECUTION_CONTEXT));
  851. //
  852. // Use the debug options if specified.
  853. //
  854. if (AcpiDebugExecutionOptions != 0) {
  855. RtlDebugPrint("ACPI: Overriding AML execution options from 0x%08x to "
  856. "0x%08x.\n",
  857. Options,
  858. AcpiDebugExecutionOptions);
  859. Options = AcpiDebugExecutionOptions;
  860. }
  861. //
  862. // Set the options.
  863. //
  864. if ((Options & AML_EXECUTION_OPTION_RUN) != 0) {
  865. NewContext->ExecuteStatements = TRUE;
  866. }
  867. if ((Options & AML_EXECUTION_OPTION_PRINT) != 0) {
  868. NewContext->PrintStatements = TRUE;
  869. }
  870. INITIALIZE_LIST_HEAD(&(NewContext->StatementStackHead));
  871. CreateAmlExecutionContextEnd:
  872. return NewContext;
  873. }
  874. VOID
  875. AcpipDestroyAmlExecutionContext (
  876. PAML_EXECUTION_CONTEXT Context
  877. )
  878. /*++
  879. Routine Description:
  880. This routine destroys an ACPI execution context.
  881. Arguments:
  882. Context - Supplies a pointer to the execution context.
  883. Return Value:
  884. None.
  885. --*/
  886. {
  887. //
  888. // Destroy the current method context.
  889. //
  890. if (Context->CurrentMethod != NULL) {
  891. AcpipPopCurrentMethodContext(Context);
  892. ASSERT(Context->CurrentMethod == NULL);
  893. }
  894. //
  895. // Destroy the return value. The caller had better upped the reference count
  896. // if it was desired.
  897. //
  898. if (Context->ReturnValue != NULL) {
  899. AcpipObjectReleaseReference(Context->ReturnValue);
  900. }
  901. AcpipFreeMemory(Context);
  902. return;
  903. }
  904. KSTATUS
  905. AcpipExecuteAml (
  906. PAML_EXECUTION_CONTEXT Context
  907. )
  908. /*++
  909. Routine Description:
  910. This routine executes a block of ACPI AML.
  911. Arguments:
  912. Context - Supplies a pointer to an initialized AML execution context.
  913. Return Value:
  914. Status code indicating whether the given block of AML was processed
  915. successfully.
  916. --*/
  917. {
  918. PLIST_ENTRY CurrentEntry;
  919. PAML_STATEMENT Statement;
  920. KSTATUS Status;
  921. //
  922. // Loop while not all of the AML has been processed.
  923. //
  924. while (TRUE) {
  925. //
  926. // Attempt to process the currently executing statement at the top
  927. // of the stack.
  928. //
  929. if (LIST_EMPTY(&(Context->StatementStackHead)) == FALSE) {
  930. CurrentEntry = Context->StatementStackHead.Next;
  931. Statement = LIST_VALUE(CurrentEntry, AML_STATEMENT, ListEntry);
  932. //
  933. // Attempt to evaluate the statement at the top of the stack.
  934. //
  935. Status = AcpipEvaluateStatement(Context, Statement);
  936. //
  937. // If there was a previous statement, free it.
  938. //
  939. if (Context->PreviousStatement != NULL) {
  940. AcpipDestroyStatement(Context->PreviousStatement);
  941. Context->PreviousStatement = NULL;
  942. }
  943. //
  944. // If the statement executed successfully, save it as the previous
  945. // statement, and pop up the stack to hand it to the parent
  946. // instruction.
  947. //
  948. if (KSUCCESS(Status)) {
  949. LIST_REMOVE(&(Statement->ListEntry));
  950. Context->PreviousStatement = Statement;
  951. //
  952. // Check to see if the previous statement resolved to a method.
  953. // If it did, push an executing method statement on to gather
  954. // arguments and then execute the method.
  955. //
  956. if ((Statement->Reduction != NULL) &&
  957. (Statement->Reduction->Type == AcpiObjectMethod)) {
  958. Status = AcpipCreateExecutingMethodStatement(Context,
  959. &Statement);
  960. if (!KSUCCESS(Status)) {
  961. goto ExecuteAmlEnd;
  962. }
  963. INSERT_AFTER(&(Statement->ListEntry),
  964. &(Context->StatementStackHead));
  965. }
  966. continue;
  967. }
  968. //
  969. // Bail if the error was anything other than "not done yet".
  970. //
  971. if (Status != STATUS_MORE_PROCESSING_REQUIRED) {
  972. ASSERT(FALSE);
  973. goto ExecuteAmlEnd;
  974. }
  975. }
  976. //
  977. // If there was a previous statement, free it.
  978. //
  979. if (Context->PreviousStatement != NULL) {
  980. AcpipDestroyStatement(Context->PreviousStatement);
  981. Context->PreviousStatement = NULL;
  982. }
  983. //
  984. // If this is the end of the AML code, finish.
  985. //
  986. if (Context->CurrentOffset == Context->AmlCodeSize) {
  987. //
  988. // All statements had better be done.
  989. //
  990. ASSERT(LIST_EMPTY(&(Context->StatementStackHead)) != FALSE);
  991. AcpipPrintIndentedNewLine(Context);
  992. break;
  993. }
  994. //
  995. // If the list was empty, this is definitely the beginning of a new
  996. // statement, so print a newline.
  997. //
  998. if (LIST_EMPTY(&(Context->StatementStackHead)) != FALSE) {
  999. AcpipPrintIndentedNewLine(Context);
  1000. }
  1001. //
  1002. // Create the next AML statement and put it on the stack.
  1003. //
  1004. Status = AcpipCreateNextStatement(Context, &Statement);
  1005. if (!KSUCCESS(Status)) {
  1006. goto ExecuteAmlEnd;
  1007. }
  1008. INSERT_AFTER(&(Statement->ListEntry), &(Context->StatementStackHead));
  1009. }
  1010. Status = STATUS_SUCCESS;
  1011. ExecuteAmlEnd:
  1012. return Status;
  1013. }
  1014. KSTATUS
  1015. AcpipCreateNextStatement (
  1016. PAML_EXECUTION_CONTEXT Context,
  1017. PAML_STATEMENT *NextStatement
  1018. )
  1019. /*++
  1020. Routine Description:
  1021. This routine creates the next AML statement based on the current AML
  1022. execution context.
  1023. Arguments:
  1024. Context - Supplies a pointer to an initialized AML execution context. The
  1025. next statement will be created based on the current execution offset.
  1026. The current offset of the context will be incremented beyond the portion
  1027. of this statement that was successfully parsed.
  1028. NextStatement - Supplies a pointer where a pointer to the next statement
  1029. will be returned. The caller is responsible for freeing this memory.
  1030. Return Value:
  1031. Status code indicating whether a statement was successfully created.
  1032. --*/
  1033. {
  1034. PAML_CREATE_NEXT_STATEMENT_ROUTINE CreateNextStatementRoutine;
  1035. UCHAR FirstByte;
  1036. PAML_STATEMENT Statement;
  1037. KSTATUS Status;
  1038. ASSERT(Context->CurrentOffset < Context->AmlCodeSize);
  1039. //
  1040. // Allocate and initialize the next statement structure.
  1041. //
  1042. Statement = AcpipCreateStatement();
  1043. if (Statement == NULL) {
  1044. Status = STATUS_INSUFFICIENT_RESOURCES;
  1045. goto CreateNextStatementEnd;
  1046. }
  1047. //
  1048. // Get the first byte of the opcode, and use that as an index into the table
  1049. // of functions that create the correct statement based on the opcode byte.
  1050. //
  1051. FirstByte = *((PUCHAR)(Context->AmlCode) + Context->CurrentOffset);
  1052. CreateNextStatementRoutine = AcpiCreateStatement[FirstByte];
  1053. Status = CreateNextStatementRoutine(Context, Statement);
  1054. if (!KSUCCESS(Status)) {
  1055. RtlDebugPrint("\nACPI: Failed to create statement. "
  1056. "Status %x, Routine %x, Context %x\n",
  1057. Status,
  1058. CreateNextStatementRoutine,
  1059. Context);
  1060. ASSERT(FALSE);
  1061. goto CreateNextStatementEnd;
  1062. }
  1063. CreateNextStatementEnd:
  1064. if (!KSUCCESS(Status)) {
  1065. if (Statement != NULL) {
  1066. AcpipFreeMemory(Statement);
  1067. Statement = NULL;
  1068. }
  1069. }
  1070. *NextStatement = Statement;
  1071. return Status;
  1072. }
  1073. VOID
  1074. AcpipDestroyStatement (
  1075. PAML_STATEMENT Statement
  1076. )
  1077. /*++
  1078. Routine Description:
  1079. This routine destroys an AML statement object.
  1080. Arguments:
  1081. Statement - Supplies a pointer to the statement to destroy. This routine
  1082. will also free any objects in the arguments list that are not owned
  1083. by a namespace.
  1084. Return Value:
  1085. None.
  1086. --*/
  1087. {
  1088. ULONG ArgumentIndex;
  1089. for (ArgumentIndex = 0;
  1090. ArgumentIndex < Statement->ArgumentsAcquired;
  1091. ArgumentIndex += 1) {
  1092. if (Statement->Argument[ArgumentIndex] != NULL) {
  1093. AcpipObjectReleaseReference(Statement->Argument[ArgumentIndex]);
  1094. }
  1095. }
  1096. if (Statement->Reduction != NULL) {
  1097. AcpipObjectReleaseReference(Statement->Reduction);
  1098. }
  1099. AcpipFreeMemory(Statement);
  1100. return;
  1101. }
  1102. KSTATUS
  1103. AcpipEvaluateStatement (
  1104. PAML_EXECUTION_CONTEXT Context,
  1105. PAML_STATEMENT Statement
  1106. )
  1107. /*++
  1108. Routine Description:
  1109. This routine attempts to evaluate an AML statement.
  1110. Arguments:
  1111. Context - Supplies a pointer to an initialized AML execution context.
  1112. Statement - Supplies a pointer to the statement to evaluate.
  1113. Return Value:
  1114. Status code.
  1115. --*/
  1116. {
  1117. PAML_EVALUATE_STATEMENT_ROUTINE EvaluateRoutine;
  1118. KSTATUS Status;
  1119. EvaluateRoutine = AcpiEvaluateStatement[Statement->Type];
  1120. ASSERT(EvaluateRoutine != NULL);
  1121. Status = EvaluateRoutine(Context, Statement);
  1122. if ((!KSUCCESS(Status)) && (Status != STATUS_MORE_PROCESSING_REQUIRED)) {
  1123. RtlDebugPrint("\nACPI: Failed to evaluate AML statement. Status: %x, "
  1124. "Context %x, Statement %x\n",
  1125. Status,
  1126. Context,
  1127. Statement);
  1128. ASSERT(FALSE);
  1129. goto EvaluateStatementEnd;
  1130. }
  1131. EvaluateStatementEnd:
  1132. return Status;
  1133. }
  1134. PAML_STATEMENT
  1135. AcpipCreateStatement (
  1136. )
  1137. /*++
  1138. Routine Description:
  1139. This routine allocates and initializes a blank AML statement.
  1140. Arguments:
  1141. None.
  1142. Return Value:
  1143. Returns a pointer to the allocated statement on success.
  1144. NULL on allocation failure.
  1145. --*/
  1146. {
  1147. PAML_STATEMENT Statement;
  1148. //
  1149. // Allocate the next statement structure.
  1150. //
  1151. Statement = AcpipAllocateMemory(sizeof(AML_STATEMENT));
  1152. if (Statement == NULL) {
  1153. goto CreateStatementEnd;
  1154. }
  1155. //
  1156. // Initialize just the essential fields, as this is a very hot path.
  1157. //
  1158. Statement->Reduction = NULL;
  1159. Statement->ArgumentsAcquired = 0;
  1160. CreateStatementEnd:
  1161. return Statement;
  1162. }
  1163. KSTATUS
  1164. AcpipCreateExecutingMethodStatement (
  1165. PAML_EXECUTION_CONTEXT Context,
  1166. PAML_STATEMENT *NextStatement
  1167. )
  1168. /*++
  1169. Routine Description:
  1170. This routine creates an executing method statement.
  1171. Arguments:
  1172. Context - Supplies a pointer to an initialized AML execution context.
  1173. NextStatement - Supplies a pointer where a pointer to the next statement
  1174. will be returned. The caller is responsible for freeing this memory.
  1175. Return Value:
  1176. Status code indicating whether a statement was successfully created.
  1177. --*/
  1178. {
  1179. PAML_STATEMENT Statement;
  1180. KSTATUS Status;
  1181. Statement = AcpipCreateStatement();
  1182. if (Statement == NULL) {
  1183. Status = STATUS_INSUFFICIENT_RESOURCES;
  1184. goto CreateExecutingMethodStatementEnd;
  1185. }
  1186. Statement->Type = AmlStatementExecutingMethod;
  1187. Statement->ArgumentsNeeded = 0;
  1188. Statement->ArgumentsAcquired = 0;
  1189. //
  1190. // Set additional data to NULL to indicate the first time the executing
  1191. // method statement is evaluated.
  1192. //
  1193. Statement->AdditionalData = (UINTN)NULL;
  1194. Status = STATUS_SUCCESS;
  1195. //
  1196. // Initialize Additional Data 2 to zero for now. It will eventually hold
  1197. // the original method context.
  1198. //
  1199. Statement->AdditionalData2 = 0;
  1200. CreateExecutingMethodStatementEnd:
  1201. *NextStatement = Statement;
  1202. return Status;
  1203. }
  1204. KSTATUS
  1205. AcpipRunInitializationMethods (
  1206. PACPI_OBJECT RootObject
  1207. )
  1208. /*++
  1209. Routine Description:
  1210. This routine runs immediately after a definition block has been loaded. As
  1211. defined by the ACPI spec, it runs all applicable _INI methods on devices.
  1212. Arguments:
  1213. RootObject - Supplies a pointer to the object to start from. If NULL is
  1214. supplied, the root system bus object \_SB will be used.
  1215. Return Value:
  1216. Status code. Failure means something serious went wrong, not just that some
  1217. device returned a non-functioning status.
  1218. --*/
  1219. {
  1220. PACPI_OBJECT CurrentObject;
  1221. PACPI_OBJECT PreviousObject;
  1222. PACPI_OBJECT PreviousSibling;
  1223. KSTATUS Status;
  1224. BOOL TraverseDown;
  1225. if (RootObject == NULL) {
  1226. RootObject = AcpipGetSystemBusRoot();
  1227. }
  1228. CurrentObject = RootObject;
  1229. PreviousObject = CurrentObject->Parent;
  1230. while (CurrentObject != NULL) {
  1231. //
  1232. // If this is the first time the node is being visited (via parent or
  1233. // sibling, but not child), then process it.
  1234. //
  1235. PreviousSibling = LIST_VALUE(CurrentObject->SiblingListEntry.Previous,
  1236. ACPI_OBJECT,
  1237. SiblingListEntry);
  1238. if ((PreviousObject == CurrentObject->Parent) ||
  1239. ((CurrentObject->SiblingListEntry.Previous != NULL) &&
  1240. (PreviousObject == PreviousSibling))) {
  1241. TraverseDown = TRUE;
  1242. if (CurrentObject->Type == AcpiObjectDevice) {
  1243. Status = AcpipRunDeviceInitialization(CurrentObject,
  1244. &TraverseDown);
  1245. if (!KSUCCESS(Status)) {
  1246. goto RunInitializationMethodsEnd;
  1247. }
  1248. }
  1249. //
  1250. // Move to the first child if eligible.
  1251. //
  1252. PreviousObject = CurrentObject;
  1253. if ((TraverseDown != FALSE) &&
  1254. (LIST_EMPTY(&(CurrentObject->ChildListHead)) == FALSE)) {
  1255. CurrentObject = LIST_VALUE(CurrentObject->ChildListHead.Next,
  1256. ACPI_OBJECT,
  1257. SiblingListEntry);
  1258. //
  1259. // Move to the next sibling if possible.
  1260. //
  1261. } else if ((CurrentObject != RootObject) &&
  1262. (CurrentObject->SiblingListEntry.Next !=
  1263. &(CurrentObject->Parent->ChildListHead))) {
  1264. CurrentObject = LIST_VALUE(CurrentObject->SiblingListEntry.Next,
  1265. ACPI_OBJECT,
  1266. SiblingListEntry);
  1267. //
  1268. // There are no children and this is the last sibling, move up to
  1269. // the parent.
  1270. //
  1271. } else {
  1272. //
  1273. // This case only gets hit if the root is the only node in the
  1274. // tree.
  1275. //
  1276. if (CurrentObject == RootObject) {
  1277. CurrentObject = NULL;
  1278. } else {
  1279. CurrentObject = CurrentObject->Parent;
  1280. }
  1281. }
  1282. //
  1283. // If the node is popping up from the previous, attempt to move to
  1284. // the next sibling, or up the tree.
  1285. //
  1286. } else {
  1287. PreviousObject = CurrentObject;
  1288. if (CurrentObject == RootObject) {
  1289. CurrentObject = NULL;
  1290. } else if (CurrentObject->SiblingListEntry.Next !=
  1291. &(CurrentObject->Parent->ChildListHead)) {
  1292. CurrentObject = LIST_VALUE(CurrentObject->SiblingListEntry.Next,
  1293. ACPI_OBJECT,
  1294. SiblingListEntry);
  1295. } else {
  1296. CurrentObject = CurrentObject->Parent;
  1297. }
  1298. }
  1299. }
  1300. Status = STATUS_SUCCESS;
  1301. RunInitializationMethodsEnd:
  1302. return Status;
  1303. }
  1304. KSTATUS
  1305. AcpipRunDeviceInitialization (
  1306. PACPI_OBJECT Device,
  1307. PBOOL TraverseDown
  1308. )
  1309. /*++
  1310. Routine Description:
  1311. This routine runs the _INI initialization method on a device, if it exists.
  1312. Arguments:
  1313. Device - Supplies a pointer to the device to initialize.
  1314. TraverseDown - Supplies a pointer where a boolean will be returned
  1315. indicating whether or not any of the device's children should be
  1316. initialized.
  1317. Return Value:
  1318. Status code. Failure means something serious went wrong, not just that the
  1319. device returned a non-functioning status.
  1320. --*/
  1321. {
  1322. ULONG DeviceStatus;
  1323. BOOL EvaluateChildren;
  1324. PACPI_OBJECT InitializationMethod;
  1325. KSTATUS Status;
  1326. ASSERT(Device->Type == AcpiObjectDevice);
  1327. DeviceStatus = ACPI_DEFAULT_DEVICE_STATUS;
  1328. EvaluateChildren = TRUE;
  1329. Status = AcpipGetDeviceStatus(Device, &DeviceStatus);
  1330. if (!KSUCCESS(Status)) {
  1331. goto RunDeviceInitializationEnd;
  1332. }
  1333. //
  1334. // Do not evaluate children if the device is neither present nor functional.
  1335. //
  1336. if (((DeviceStatus & ACPI_DEVICE_STATUS_FUNCTIONING_PROPERLY) == 0) &&
  1337. ((DeviceStatus & ACPI_DEVICE_STATUS_PRESENT) == 0)) {
  1338. EvaluateChildren = FALSE;
  1339. }
  1340. //
  1341. // If the device is not present, do not run the _INI method.
  1342. //
  1343. if ((DeviceStatus & ACPI_DEVICE_STATUS_PRESENT) == 0) {
  1344. goto RunDeviceInitializationEnd;
  1345. }
  1346. InitializationMethod = AcpipFindNamedObject(Device, ACPI_METHOD__INI);
  1347. if (InitializationMethod == NULL) {
  1348. goto RunDeviceInitializationEnd;
  1349. }
  1350. Status = AcpiExecuteMethod(InitializationMethod, NULL, 0, 0, NULL);
  1351. if (!KSUCCESS(Status)) {
  1352. goto RunDeviceInitializationEnd;
  1353. }
  1354. RunDeviceInitializationEnd:
  1355. *TraverseDown = EvaluateChildren;
  1356. return Status;
  1357. }