psloop.c revision 1.1.1.2.8.2 1 /******************************************************************************
2 *
3 * Module Name: psloop - Main AML parse loop
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2011, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45 /*
46 * Parse the AML and build an operation tree as most interpreters, (such as
47 * Perl) do. Parsing is done by hand rather than with a YACC generated parser
48 * to tightly constrain stack and dynamic memory usage. Parsing is kept
49 * flexible and the code fairly compact by parsing based on a list of AML
50 * opcode templates in AmlOpInfo[].
51 */
52
53 #include "acpi.h"
54 #include "accommon.h"
55 #include "acparser.h"
56 #include "acdispat.h"
57 #include "amlcode.h"
58
59 #define _COMPONENT ACPI_PARSER
60 ACPI_MODULE_NAME ("psloop")
61
62 static UINT32 AcpiGbl_Depth = 0;
63
64
65 /* Local prototypes */
66
67 static ACPI_STATUS
68 AcpiPsGetAmlOpcode (
69 ACPI_WALK_STATE *WalkState);
70
71 static ACPI_STATUS
72 AcpiPsBuildNamedOp (
73 ACPI_WALK_STATE *WalkState,
74 UINT8 *AmlOpStart,
75 ACPI_PARSE_OBJECT *UnnamedOp,
76 ACPI_PARSE_OBJECT **Op);
77
78 static ACPI_STATUS
79 AcpiPsCreateOp (
80 ACPI_WALK_STATE *WalkState,
81 UINT8 *AmlOpStart,
82 ACPI_PARSE_OBJECT **NewOp);
83
84 static ACPI_STATUS
85 AcpiPsGetArguments (
86 ACPI_WALK_STATE *WalkState,
87 UINT8 *AmlOpStart,
88 ACPI_PARSE_OBJECT *Op);
89
90 static ACPI_STATUS
91 AcpiPsCompleteOp (
92 ACPI_WALK_STATE *WalkState,
93 ACPI_PARSE_OBJECT **Op,
94 ACPI_STATUS Status);
95
96 static ACPI_STATUS
97 AcpiPsCompleteFinalOp (
98 ACPI_WALK_STATE *WalkState,
99 ACPI_PARSE_OBJECT *Op,
100 ACPI_STATUS Status);
101
102 static void
103 AcpiPsLinkModuleCode (
104 ACPI_PARSE_OBJECT *ParentOp,
105 UINT8 *AmlStart,
106 UINT32 AmlLength,
107 ACPI_OWNER_ID OwnerId);
108
109
110 /*******************************************************************************
111 *
112 * FUNCTION: AcpiPsGetAmlOpcode
113 *
114 * PARAMETERS: WalkState - Current state
115 *
116 * RETURN: Status
117 *
118 * DESCRIPTION: Extract the next AML opcode from the input stream.
119 *
120 ******************************************************************************/
121
122 static ACPI_STATUS
123 AcpiPsGetAmlOpcode (
124 ACPI_WALK_STATE *WalkState)
125 {
126
127 ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState);
128
129
130 WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml,
131 WalkState->ParserState.AmlStart);
132 WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState));
133
134 /*
135 * First cut to determine what we have found:
136 * 1) A valid AML opcode
137 * 2) A name string
138 * 3) An unknown/invalid opcode
139 */
140 WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
141
142 switch (WalkState->OpInfo->Class)
143 {
144 case AML_CLASS_ASCII:
145 case AML_CLASS_PREFIX:
146 /*
147 * Starts with a valid prefix or ASCII char, this is a name
148 * string. Convert the bare name string to a namepath.
149 */
150 WalkState->Opcode = AML_INT_NAMEPATH_OP;
151 WalkState->ArgTypes = ARGP_NAMESTRING;
152 break;
153
154 case AML_CLASS_UNKNOWN:
155
156 /* The opcode is unrecognized. Just skip unknown opcodes */
157
158 ACPI_ERROR ((AE_INFO,
159 "Found unknown opcode 0x%X at AML address %p offset 0x%X, ignoring",
160 WalkState->Opcode, WalkState->ParserState.Aml, WalkState->AmlOffset));
161
162 ACPI_DUMP_BUFFER (WalkState->ParserState.Aml, 128);
163
164 /* Assume one-byte bad opcode */
165
166 WalkState->ParserState.Aml++;
167 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
168
169 default:
170
171 /* Found opcode info, this is a normal opcode */
172
173 WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode);
174 WalkState->ArgTypes = WalkState->OpInfo->ParseArgs;
175 break;
176 }
177
178 return_ACPI_STATUS (AE_OK);
179 }
180
181
182 /*******************************************************************************
183 *
184 * FUNCTION: AcpiPsBuildNamedOp
185 *
186 * PARAMETERS: WalkState - Current state
187 * AmlOpStart - Begin of named Op in AML
188 * UnnamedOp - Early Op (not a named Op)
189 * Op - Returned Op
190 *
191 * RETURN: Status
192 *
193 * DESCRIPTION: Parse a named Op
194 *
195 ******************************************************************************/
196
197 static ACPI_STATUS
198 AcpiPsBuildNamedOp (
199 ACPI_WALK_STATE *WalkState,
200 UINT8 *AmlOpStart,
201 ACPI_PARSE_OBJECT *UnnamedOp,
202 ACPI_PARSE_OBJECT **Op)
203 {
204 ACPI_STATUS Status = AE_OK;
205 ACPI_PARSE_OBJECT *Arg = NULL;
206
207
208 ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState);
209
210
211 UnnamedOp->Common.Value.Arg = NULL;
212 UnnamedOp->Common.ArgListLength = 0;
213 UnnamedOp->Common.AmlOpcode = WalkState->Opcode;
214
215 /*
216 * Get and append arguments until we find the node that contains
217 * the name (the type ARGP_NAME).
218 */
219 while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
220 (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME))
221 {
222 Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState),
223 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
224 if (ACPI_FAILURE (Status))
225 {
226 return_ACPI_STATUS (Status);
227 }
228
229 AcpiPsAppendArg (UnnamedOp, Arg);
230 INCREMENT_ARG_LIST (WalkState->ArgTypes);
231 }
232
233 /*
234 * Make sure that we found a NAME and didn't run out of arguments
235 */
236 if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes))
237 {
238 return_ACPI_STATUS (AE_AML_NO_OPERAND);
239 }
240
241 /* We know that this arg is a name, move to next arg */
242
243 INCREMENT_ARG_LIST (WalkState->ArgTypes);
244
245 /*
246 * Find the object. This will either insert the object into
247 * the namespace or simply look it up
248 */
249 WalkState->Op = NULL;
250
251 Status = WalkState->DescendingCallback (WalkState, Op);
252 if (ACPI_FAILURE (Status))
253 {
254 ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog"));
255 return_ACPI_STATUS (Status);
256 }
257
258 if (!*Op)
259 {
260 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
261 }
262
263 Status = AcpiPsNextParseState (WalkState, *Op, Status);
264 if (ACPI_FAILURE (Status))
265 {
266 if (Status == AE_CTRL_PENDING)
267 {
268 return_ACPI_STATUS (AE_CTRL_PARSE_PENDING);
269 }
270 return_ACPI_STATUS (Status);
271 }
272
273 AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg);
274 AcpiGbl_Depth++;
275
276 if ((*Op)->Common.AmlOpcode == AML_REGION_OP ||
277 (*Op)->Common.AmlOpcode == AML_DATA_REGION_OP)
278 {
279 /*
280 * Defer final parsing of an OperationRegion body, because we don't
281 * have enough info in the first pass to parse it correctly (i.e.,
282 * there may be method calls within the TermArg elements of the body.)
283 *
284 * However, we must continue parsing because the opregion is not a
285 * standalone package -- we don't know where the end is at this point.
286 *
287 * (Length is unknown until parse of the body complete)
288 */
289 (*Op)->Named.Data = AmlOpStart;
290 (*Op)->Named.Length = 0;
291 }
292
293 return_ACPI_STATUS (AE_OK);
294 }
295
296
297 /*******************************************************************************
298 *
299 * FUNCTION: AcpiPsCreateOp
300 *
301 * PARAMETERS: WalkState - Current state
302 * AmlOpStart - Op start in AML
303 * NewOp - Returned Op
304 *
305 * RETURN: Status
306 *
307 * DESCRIPTION: Get Op from AML
308 *
309 ******************************************************************************/
310
311 static ACPI_STATUS
312 AcpiPsCreateOp (
313 ACPI_WALK_STATE *WalkState,
314 UINT8 *AmlOpStart,
315 ACPI_PARSE_OBJECT **NewOp)
316 {
317 ACPI_STATUS Status = AE_OK;
318 ACPI_PARSE_OBJECT *Op;
319 ACPI_PARSE_OBJECT *NamedOp = NULL;
320 ACPI_PARSE_OBJECT *ParentScope;
321 UINT8 ArgumentCount;
322 const ACPI_OPCODE_INFO *OpInfo;
323
324
325 ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState);
326
327
328 Status = AcpiPsGetAmlOpcode (WalkState);
329 if (Status == AE_CTRL_PARSE_CONTINUE)
330 {
331 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
332 }
333
334 /* Create Op structure and append to parent's argument list */
335
336 WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
337 Op = AcpiPsAllocOp (WalkState->Opcode);
338 if (!Op)
339 {
340 return_ACPI_STATUS (AE_NO_MEMORY);
341 }
342
343 if (WalkState->OpInfo->Flags & AML_NAMED)
344 {
345 Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp);
346 AcpiPsFreeOp (Op);
347 if (ACPI_FAILURE (Status))
348 {
349 return_ACPI_STATUS (Status);
350 }
351
352 *NewOp = NamedOp;
353 return_ACPI_STATUS (AE_OK);
354 }
355
356 /* Not a named opcode, just allocate Op and append to parent */
357
358 if (WalkState->OpInfo->Flags & AML_CREATE)
359 {
360 /*
361 * Backup to beginning of CreateXXXfield declaration
362 * BodyLength is unknown until we parse the body
363 */
364 Op->Named.Data = AmlOpStart;
365 Op->Named.Length = 0;
366 }
367
368 if (WalkState->Opcode == AML_BANK_FIELD_OP)
369 {
370 /*
371 * Backup to beginning of BankField declaration
372 * BodyLength is unknown until we parse the body
373 */
374 Op->Named.Data = AmlOpStart;
375 Op->Named.Length = 0;
376 }
377
378 ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState));
379 AcpiPsAppendArg (ParentScope, Op);
380
381 if (ParentScope)
382 {
383 OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode);
384 if (OpInfo->Flags & AML_HAS_TARGET)
385 {
386 ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type);
387 if (ParentScope->Common.ArgListLength > ArgumentCount)
388 {
389 Op->Common.Flags |= ACPI_PARSEOP_TARGET;
390 }
391 }
392 else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP)
393 {
394 Op->Common.Flags |= ACPI_PARSEOP_TARGET;
395 }
396 }
397
398 if (WalkState->DescendingCallback != NULL)
399 {
400 /*
401 * Find the object. This will either insert the object into
402 * the namespace or simply look it up
403 */
404 WalkState->Op = *NewOp = Op;
405
406 Status = WalkState->DescendingCallback (WalkState, &Op);
407 Status = AcpiPsNextParseState (WalkState, Op, Status);
408 if (Status == AE_CTRL_PENDING)
409 {
410 Status = AE_CTRL_PARSE_PENDING;
411 }
412 }
413
414 return_ACPI_STATUS (Status);
415 }
416
417
418 /*******************************************************************************
419 *
420 * FUNCTION: AcpiPsGetArguments
421 *
422 * PARAMETERS: WalkState - Current state
423 * AmlOpStart - Op start in AML
424 * Op - Current Op
425 *
426 * RETURN: Status
427 *
428 * DESCRIPTION: Get arguments for passed Op.
429 *
430 ******************************************************************************/
431
432 static ACPI_STATUS
433 AcpiPsGetArguments (
434 ACPI_WALK_STATE *WalkState,
435 UINT8 *AmlOpStart,
436 ACPI_PARSE_OBJECT *Op)
437 {
438 ACPI_STATUS Status = AE_OK;
439 ACPI_PARSE_OBJECT *Arg = NULL;
440 const ACPI_OPCODE_INFO *OpInfo;
441
442
443 ACPI_FUNCTION_TRACE_PTR (PsGetArguments, WalkState);
444
445
446 switch (Op->Common.AmlOpcode)
447 {
448 case AML_BYTE_OP: /* AML_BYTEDATA_ARG */
449 case AML_WORD_OP: /* AML_WORDDATA_ARG */
450 case AML_DWORD_OP: /* AML_DWORDATA_ARG */
451 case AML_QWORD_OP: /* AML_QWORDATA_ARG */
452 case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */
453
454 /* Fill in constant or string argument directly */
455
456 AcpiPsGetNextSimpleArg (&(WalkState->ParserState),
457 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), Op);
458 break;
459
460 case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */
461
462 Status = AcpiPsGetNextNamepath (WalkState, &(WalkState->ParserState), Op, 1);
463 if (ACPI_FAILURE (Status))
464 {
465 return_ACPI_STATUS (Status);
466 }
467
468 WalkState->ArgTypes = 0;
469 break;
470
471 default:
472 /*
473 * Op is not a constant or string, append each argument to the Op
474 */
475 while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && !WalkState->ArgCount)
476 {
477 WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml,
478 WalkState->ParserState.AmlStart);
479
480 Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState),
481 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
482 if (ACPI_FAILURE (Status))
483 {
484 return_ACPI_STATUS (Status);
485 }
486
487 if (Arg)
488 {
489 Arg->Common.AmlOffset = WalkState->AmlOffset;
490 AcpiPsAppendArg (Op, Arg);
491 }
492
493 INCREMENT_ARG_LIST (WalkState->ArgTypes);
494 }
495
496
497 /*
498 * Handle executable code at "module-level". This refers to
499 * executable opcodes that appear outside of any control method.
500 */
501 if ((WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2) &&
502 ((WalkState->ParseFlags & ACPI_PARSE_DISASSEMBLE) == 0))
503 {
504 /*
505 * We want to skip If/Else/While constructs during Pass1 because we
506 * want to actually conditionally execute the code during Pass2.
507 *
508 * Except for disassembly, where we always want to walk the
509 * If/Else/While packages
510 */
511 switch (Op->Common.AmlOpcode)
512 {
513 case AML_IF_OP:
514 case AML_ELSE_OP:
515 case AML_WHILE_OP:
516
517 /*
518 * Currently supported module-level opcodes are:
519 * IF/ELSE/WHILE. These appear to be the most common,
520 * and easiest to support since they open an AML
521 * package.
522 */
523 if (WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1)
524 {
525 AcpiPsLinkModuleCode (Op->Common.Parent, AmlOpStart,
526 (UINT32) (WalkState->ParserState.PkgEnd - AmlOpStart),
527 WalkState->OwnerId);
528 }
529
530 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
531 "Pass1: Skipping an If/Else/While body\n"));
532
533 /* Skip body of if/else/while in pass 1 */
534
535 WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd;
536 WalkState->ArgCount = 0;
537 break;
538
539 default:
540 /*
541 * Check for an unsupported executable opcode at module
542 * level. We must be in PASS1, the parent must be a SCOPE,
543 * The opcode class must be EXECUTE, and the opcode must
544 * not be an argument to another opcode.
545 */
546 if ((WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1) &&
547 (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP))
548 {
549 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
550 if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
551 (!Arg))
552 {
553 ACPI_WARNING ((AE_INFO,
554 "Detected an unsupported executable opcode "
555 "at module-level: [0x%.4X] at table offset 0x%.4X",
556 Op->Common.AmlOpcode,
557 (UINT32) (ACPI_PTR_DIFF (AmlOpStart,
558 WalkState->ParserState.AmlStart) +
559 sizeof (ACPI_TABLE_HEADER))));
560 }
561 }
562 break;
563 }
564 }
565
566 /* Special processing for certain opcodes */
567
568 switch (Op->Common.AmlOpcode)
569 {
570 case AML_METHOD_OP:
571 /*
572 * Skip parsing of control method because we don't have enough
573 * info in the first pass to parse it correctly.
574 *
575 * Save the length and address of the body
576 */
577 Op->Named.Data = WalkState->ParserState.Aml;
578 Op->Named.Length = (UINT32)
579 (WalkState->ParserState.PkgEnd - WalkState->ParserState.Aml);
580
581 /* Skip body of method */
582
583 WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd;
584 WalkState->ArgCount = 0;
585 break;
586
587 case AML_BUFFER_OP:
588 case AML_PACKAGE_OP:
589 case AML_VAR_PACKAGE_OP:
590
591 if ((Op->Common.Parent) &&
592 (Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) &&
593 (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2))
594 {
595 /*
596 * Skip parsing of Buffers and Packages because we don't have
597 * enough info in the first pass to parse them correctly.
598 */
599 Op->Named.Data = AmlOpStart;
600 Op->Named.Length = (UINT32)
601 (WalkState->ParserState.PkgEnd - AmlOpStart);
602
603 /* Skip body */
604
605 WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd;
606 WalkState->ArgCount = 0;
607 }
608 break;
609
610 case AML_WHILE_OP:
611
612 if (WalkState->ControlState)
613 {
614 WalkState->ControlState->Control.PackageEnd =
615 WalkState->ParserState.PkgEnd;
616 }
617 break;
618
619 default:
620
621 /* No action for all other opcodes */
622 break;
623 }
624
625 break;
626 }
627
628 return_ACPI_STATUS (AE_OK);
629 }
630
631
632 /*******************************************************************************
633 *
634 * FUNCTION: AcpiPsLinkModuleCode
635 *
636 * PARAMETERS: ParentOp - Parent parser op
637 * AmlStart - Pointer to the AML
638 * AmlLength - Length of executable AML
639 * OwnerId - OwnerId of module level code
640 *
641 * RETURN: None.
642 *
643 * DESCRIPTION: Wrap the module-level code with a method object and link the
644 * object to the global list. Note, the mutex field of the method
645 * object is used to link multiple module-level code objects.
646 *
647 ******************************************************************************/
648
649 static void
650 AcpiPsLinkModuleCode (
651 ACPI_PARSE_OBJECT *ParentOp,
652 UINT8 *AmlStart,
653 UINT32 AmlLength,
654 ACPI_OWNER_ID OwnerId)
655 {
656 ACPI_OPERAND_OBJECT *Prev;
657 ACPI_OPERAND_OBJECT *Next;
658 ACPI_OPERAND_OBJECT *MethodObj;
659 ACPI_NAMESPACE_NODE *ParentNode;
660
661
662 /* Get the tail of the list */
663
664 Prev = Next = AcpiGbl_ModuleCodeList;
665 while (Next)
666 {
667 Prev = Next;
668 Next = Next->Method.Mutex;
669 }
670
671 /*
672 * Insert the module level code into the list. Merge it if it is
673 * adjacent to the previous element.
674 */
675 if (!Prev ||
676 ((Prev->Method.AmlStart + Prev->Method.AmlLength) != AmlStart))
677 {
678 /* Create, initialize, and link a new temporary method object */
679
680 MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
681 if (!MethodObj)
682 {
683 return;
684 }
685
686 if (ParentOp->Common.Node)
687 {
688 ParentNode = ParentOp->Common.Node;
689 }
690 else
691 {
692 ParentNode = AcpiGbl_RootNode;
693 }
694
695 MethodObj->Method.AmlStart = AmlStart;
696 MethodObj->Method.AmlLength = AmlLength;
697 MethodObj->Method.OwnerId = OwnerId;
698 MethodObj->Method.InfoFlags |= ACPI_METHOD_MODULE_LEVEL;
699
700 /*
701 * Save the parent node in NextObject. This is cheating, but we
702 * don't want to expand the method object.
703 */
704 MethodObj->Method.NextObject =
705 ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, ParentNode);
706
707 if (!Prev)
708 {
709 AcpiGbl_ModuleCodeList = MethodObj;
710 }
711 else
712 {
713 Prev->Method.Mutex = MethodObj;
714 }
715 }
716 else
717 {
718 Prev->Method.AmlLength += AmlLength;
719 }
720 }
721
722
723 /*******************************************************************************
724 *
725 * FUNCTION: AcpiPsCompleteOp
726 *
727 * PARAMETERS: WalkState - Current state
728 * Op - Returned Op
729 * Status - Parse status before complete Op
730 *
731 * RETURN: Status
732 *
733 * DESCRIPTION: Complete Op
734 *
735 ******************************************************************************/
736
737 static ACPI_STATUS
738 AcpiPsCompleteOp (
739 ACPI_WALK_STATE *WalkState,
740 ACPI_PARSE_OBJECT **Op,
741 ACPI_STATUS Status)
742 {
743 ACPI_STATUS Status2;
744
745
746 ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState);
747
748
749 /*
750 * Finished one argument of the containing scope
751 */
752 WalkState->ParserState.Scope->ParseScope.ArgCount--;
753
754 /* Close this Op (will result in parse subtree deletion) */
755
756 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
757 if (ACPI_FAILURE (Status2))
758 {
759 return_ACPI_STATUS (Status2);
760 }
761
762 *Op = NULL;
763
764 switch (Status)
765 {
766 case AE_OK:
767 break;
768
769
770 case AE_CTRL_TRANSFER:
771
772 /* We are about to transfer to a called method */
773
774 WalkState->PrevOp = NULL;
775 WalkState->PrevArgTypes = WalkState->ArgTypes;
776 return_ACPI_STATUS (Status);
777
778
779 case AE_CTRL_END:
780
781 AcpiPsPopScope (&(WalkState->ParserState), Op,
782 &WalkState->ArgTypes, &WalkState->ArgCount);
783
784 if (*Op)
785 {
786 WalkState->Op = *Op;
787 WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
788 WalkState->Opcode = (*Op)->Common.AmlOpcode;
789
790 Status = WalkState->AscendingCallback (WalkState);
791 Status = AcpiPsNextParseState (WalkState, *Op, Status);
792
793 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
794 if (ACPI_FAILURE (Status2))
795 {
796 return_ACPI_STATUS (Status2);
797 }
798 }
799
800 Status = AE_OK;
801 break;
802
803
804 case AE_CTRL_BREAK:
805 case AE_CTRL_CONTINUE:
806
807 /* Pop off scopes until we find the While */
808
809 while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP))
810 {
811 AcpiPsPopScope (&(WalkState->ParserState), Op,
812 &WalkState->ArgTypes, &WalkState->ArgCount);
813 }
814
815 /* Close this iteration of the While loop */
816
817 WalkState->Op = *Op;
818 WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
819 WalkState->Opcode = (*Op)->Common.AmlOpcode;
820
821 Status = WalkState->AscendingCallback (WalkState);
822 Status = AcpiPsNextParseState (WalkState, *Op, Status);
823
824 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
825 if (ACPI_FAILURE (Status2))
826 {
827 return_ACPI_STATUS (Status2);
828 }
829
830 Status = AE_OK;
831 break;
832
833
834 case AE_CTRL_TERMINATE:
835
836 /* Clean up */
837 do
838 {
839 if (*Op)
840 {
841 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
842 if (ACPI_FAILURE (Status2))
843 {
844 return_ACPI_STATUS (Status2);
845 }
846
847 AcpiUtDeleteGenericState (
848 AcpiUtPopGenericState (&WalkState->ControlState));
849 }
850
851 AcpiPsPopScope (&(WalkState->ParserState), Op,
852 &WalkState->ArgTypes, &WalkState->ArgCount);
853
854 } while (*Op);
855
856 return_ACPI_STATUS (AE_OK);
857
858
859 default: /* All other non-AE_OK status */
860
861 do
862 {
863 if (*Op)
864 {
865 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
866 if (ACPI_FAILURE (Status2))
867 {
868 return_ACPI_STATUS (Status2);
869 }
870 }
871
872 AcpiPsPopScope (&(WalkState->ParserState), Op,
873 &WalkState->ArgTypes, &WalkState->ArgCount);
874
875 } while (*Op);
876
877
878 #if 0
879 /*
880 * TBD: Cleanup parse ops on error
881 */
882 if (*Op == NULL)
883 {
884 AcpiPsPopScope (ParserState, Op,
885 &WalkState->ArgTypes, &WalkState->ArgCount);
886 }
887 #endif
888 WalkState->PrevOp = NULL;
889 WalkState->PrevArgTypes = WalkState->ArgTypes;
890 return_ACPI_STATUS (Status);
891 }
892
893 /* This scope complete? */
894
895 if (AcpiPsHasCompletedScope (&(WalkState->ParserState)))
896 {
897 AcpiPsPopScope (&(WalkState->ParserState), Op,
898 &WalkState->ArgTypes, &WalkState->ArgCount);
899 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op));
900 }
901 else
902 {
903 *Op = NULL;
904 }
905
906 return_ACPI_STATUS (AE_OK);
907 }
908
909
910 /*******************************************************************************
911 *
912 * FUNCTION: AcpiPsCompleteFinalOp
913 *
914 * PARAMETERS: WalkState - Current state
915 * Op - Current Op
916 * Status - Current parse status before complete last
917 * Op
918 *
919 * RETURN: Status
920 *
921 * DESCRIPTION: Complete last Op.
922 *
923 ******************************************************************************/
924
925 static ACPI_STATUS
926 AcpiPsCompleteFinalOp (
927 ACPI_WALK_STATE *WalkState,
928 ACPI_PARSE_OBJECT *Op,
929 ACPI_STATUS Status)
930 {
931 ACPI_STATUS Status2;
932
933
934 ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState);
935
936
937 /*
938 * Complete the last Op (if not completed), and clear the scope stack.
939 * It is easily possible to end an AML "package" with an unbounded number
940 * of open scopes (such as when several ASL blocks are closed with
941 * sequential closing braces). We want to terminate each one cleanly.
942 */
943 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op));
944 do
945 {
946 if (Op)
947 {
948 if (WalkState->AscendingCallback != NULL)
949 {
950 WalkState->Op = Op;
951 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
952 WalkState->Opcode = Op->Common.AmlOpcode;
953
954 Status = WalkState->AscendingCallback (WalkState);
955 Status = AcpiPsNextParseState (WalkState, Op, Status);
956 if (Status == AE_CTRL_PENDING)
957 {
958 Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK);
959 if (ACPI_FAILURE (Status))
960 {
961 return_ACPI_STATUS (Status);
962 }
963 }
964
965 if (Status == AE_CTRL_TERMINATE)
966 {
967 Status = AE_OK;
968
969 /* Clean up */
970 do
971 {
972 if (Op)
973 {
974 Status2 = AcpiPsCompleteThisOp (WalkState, Op);
975 if (ACPI_FAILURE (Status2))
976 {
977 return_ACPI_STATUS (Status2);
978 }
979 }
980
981 AcpiPsPopScope (&(WalkState->ParserState), &Op,
982 &WalkState->ArgTypes, &WalkState->ArgCount);
983
984 } while (Op);
985
986 return_ACPI_STATUS (Status);
987 }
988
989 else if (ACPI_FAILURE (Status))
990 {
991 /* First error is most important */
992
993 (void) AcpiPsCompleteThisOp (WalkState, Op);
994 return_ACPI_STATUS (Status);
995 }
996 }
997
998 Status2 = AcpiPsCompleteThisOp (WalkState, Op);
999 if (ACPI_FAILURE (Status2))
1000 {
1001 return_ACPI_STATUS (Status2);
1002 }
1003 }
1004
1005 AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes,
1006 &WalkState->ArgCount);
1007
1008 } while (Op);
1009
1010 return_ACPI_STATUS (Status);
1011 }
1012
1013
1014 /*******************************************************************************
1015 *
1016 * FUNCTION: AcpiPsParseLoop
1017 *
1018 * PARAMETERS: WalkState - Current state
1019 *
1020 * RETURN: Status
1021 *
1022 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
1023 * a tree of ops.
1024 *
1025 ******************************************************************************/
1026
1027 ACPI_STATUS
1028 AcpiPsParseLoop (
1029 ACPI_WALK_STATE *WalkState)
1030 {
1031 ACPI_STATUS Status = AE_OK;
1032 ACPI_PARSE_OBJECT *Op = NULL; /* current op */
1033 ACPI_PARSE_STATE *ParserState;
1034 UINT8 *AmlOpStart = NULL;
1035
1036
1037 ACPI_FUNCTION_TRACE_PTR (PsParseLoop, WalkState);
1038
1039
1040 if (WalkState->DescendingCallback == NULL)
1041 {
1042 return_ACPI_STATUS (AE_BAD_PARAMETER);
1043 }
1044
1045 ParserState = &WalkState->ParserState;
1046 WalkState->ArgTypes = 0;
1047
1048 #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
1049
1050 if (WalkState->WalkType & ACPI_WALK_METHOD_RESTART)
1051 {
1052 /* We are restarting a preempted control method */
1053
1054 if (AcpiPsHasCompletedScope (ParserState))
1055 {
1056 /*
1057 * We must check if a predicate to an IF or WHILE statement
1058 * was just completed
1059 */
1060 if ((ParserState->Scope->ParseScope.Op) &&
1061 ((ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_IF_OP) ||
1062 (ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_WHILE_OP)) &&
1063 (WalkState->ControlState) &&
1064 (WalkState->ControlState->Common.State ==
1065 ACPI_CONTROL_PREDICATE_EXECUTING))
1066 {
1067 /*
1068 * A predicate was just completed, get the value of the
1069 * predicate and branch based on that value
1070 */
1071 WalkState->Op = NULL;
1072 Status = AcpiDsGetPredicateValue (WalkState, ACPI_TO_POINTER (TRUE));
1073 if (ACPI_FAILURE (Status) &&
1074 ((Status & AE_CODE_MASK) != AE_CODE_CONTROL))
1075 {
1076 if (Status == AE_AML_NO_RETURN_VALUE)
1077 {
1078 ACPI_EXCEPTION ((AE_INFO, Status,
1079 "Invoked method did not return a value"));
1080 }
1081
1082 ACPI_EXCEPTION ((AE_INFO, Status, "GetPredicate Failed"));
1083 return_ACPI_STATUS (Status);
1084 }
1085
1086 Status = AcpiPsNextParseState (WalkState, Op, Status);
1087 }
1088
1089 AcpiPsPopScope (ParserState, &Op,
1090 &WalkState->ArgTypes, &WalkState->ArgCount);
1091 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op));
1092 }
1093 else if (WalkState->PrevOp)
1094 {
1095 /* We were in the middle of an op */
1096
1097 Op = WalkState->PrevOp;
1098 WalkState->ArgTypes = WalkState->PrevArgTypes;
1099 }
1100 }
1101 #endif
1102
1103 /* Iterative parsing loop, while there is more AML to process: */
1104
1105 while ((ParserState->Aml < ParserState->AmlEnd) || (Op))
1106 {
1107 AmlOpStart = ParserState->Aml;
1108 if (!Op)
1109 {
1110 Status = AcpiPsCreateOp (WalkState, AmlOpStart, &Op);
1111 if (ACPI_FAILURE (Status))
1112 {
1113 if (Status == AE_CTRL_PARSE_CONTINUE)
1114 {
1115 continue;
1116 }
1117
1118 if (Status == AE_CTRL_PARSE_PENDING)
1119 {
1120 Status = AE_OK;
1121 }
1122
1123 Status = AcpiPsCompleteOp (WalkState, &Op, Status);
1124 if (ACPI_FAILURE (Status))
1125 {
1126 return_ACPI_STATUS (Status);
1127 }
1128
1129 continue;
1130 }
1131
1132 Op->Common.AmlOffset = WalkState->AmlOffset;
1133
1134 if (WalkState->OpInfo)
1135 {
1136 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
1137 "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n",
1138 (UINT32) Op->Common.AmlOpcode, WalkState->OpInfo->Name,
1139 Op, ParserState->Aml, Op->Common.AmlOffset));
1140 }
1141 }
1142
1143
1144 /*
1145 * Start ArgCount at zero because we don't know if there are
1146 * any args yet
1147 */
1148 WalkState->ArgCount = 0;
1149
1150 /* Are there any arguments that must be processed? */
1151
1152 if (WalkState->ArgTypes)
1153 {
1154 /* Get arguments */
1155
1156 Status = AcpiPsGetArguments (WalkState, AmlOpStart, Op);
1157 if (ACPI_FAILURE (Status))
1158 {
1159 Status = AcpiPsCompleteOp (WalkState, &Op, Status);
1160 if (ACPI_FAILURE (Status))
1161 {
1162 return_ACPI_STATUS (Status);
1163 }
1164
1165 continue;
1166 }
1167 }
1168
1169 /* Check for arguments that need to be processed */
1170
1171 if (WalkState->ArgCount)
1172 {
1173 /*
1174 * There are arguments (complex ones), push Op and
1175 * prepare for argument
1176 */
1177 Status = AcpiPsPushScope (ParserState, Op,
1178 WalkState->ArgTypes, WalkState->ArgCount);
1179 if (ACPI_FAILURE (Status))
1180 {
1181 Status = AcpiPsCompleteOp (WalkState, &Op, Status);
1182 if (ACPI_FAILURE (Status))
1183 {
1184 return_ACPI_STATUS (Status);
1185 }
1186
1187 continue;
1188 }
1189
1190 Op = NULL;
1191 continue;
1192 }
1193
1194 /*
1195 * All arguments have been processed -- Op is complete,
1196 * prepare for next
1197 */
1198 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1199 if (WalkState->OpInfo->Flags & AML_NAMED)
1200 {
1201 if (AcpiGbl_Depth)
1202 {
1203 AcpiGbl_Depth--;
1204 }
1205
1206 if (Op->Common.AmlOpcode == AML_REGION_OP ||
1207 Op->Common.AmlOpcode == AML_DATA_REGION_OP)
1208 {
1209 /*
1210 * Skip parsing of control method or opregion body,
1211 * because we don't have enough info in the first pass
1212 * to parse them correctly.
1213 *
1214 * Completed parsing an OpRegion declaration, we now
1215 * know the length.
1216 */
1217 Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
1218 }
1219 }
1220
1221 if (WalkState->OpInfo->Flags & AML_CREATE)
1222 {
1223 /*
1224 * Backup to beginning of CreateXXXfield declaration (1 for
1225 * Opcode)
1226 *
1227 * BodyLength is unknown until we parse the body
1228 */
1229 Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
1230 }
1231
1232 if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP)
1233 {
1234 /*
1235 * Backup to beginning of BankField declaration
1236 *
1237 * BodyLength is unknown until we parse the body
1238 */
1239 Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
1240 }
1241
1242 /* This op complete, notify the dispatcher */
1243
1244 if (WalkState->AscendingCallback != NULL)
1245 {
1246 WalkState->Op = Op;
1247 WalkState->Opcode = Op->Common.AmlOpcode;
1248
1249 Status = WalkState->AscendingCallback (WalkState);
1250 Status = AcpiPsNextParseState (WalkState, Op, Status);
1251 if (Status == AE_CTRL_PENDING)
1252 {
1253 Status = AE_OK;
1254 }
1255 }
1256
1257 Status = AcpiPsCompleteOp (WalkState, &Op, Status);
1258 if (ACPI_FAILURE (Status))
1259 {
1260 return_ACPI_STATUS (Status);
1261 }
1262
1263 } /* while ParserState->Aml */
1264
1265 Status = AcpiPsCompleteFinalOp (WalkState, Op, Status);
1266 return_ACPI_STATUS (Status);
1267 }
1268
1269