1 /******************************************************************************
3 * Module Name: psobject - Support for parse objects
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2016, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
49 #define _COMPONENT ACPI_PARSER
50 ACPI_MODULE_NAME ("psobject")
53 /* Local prototypes */
57 ACPI_WALK_STATE
*WalkState
);
60 /*******************************************************************************
62 * FUNCTION: AcpiPsGetAmlOpcode
64 * PARAMETERS: WalkState - Current state
68 * DESCRIPTION: Extract the next AML opcode from the input stream.
70 ******************************************************************************/
74 ACPI_WALK_STATE
*WalkState
)
79 ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode
, WalkState
);
82 WalkState
->Aml
= WalkState
->ParserState
.Aml
;
83 WalkState
->Opcode
= AcpiPsPeekOpcode (&(WalkState
->ParserState
));
86 * First cut to determine what we have found:
87 * 1) A valid AML opcode
89 * 3) An unknown/invalid opcode
91 WalkState
->OpInfo
= AcpiPsGetOpcodeInfo (WalkState
->Opcode
);
93 switch (WalkState
->OpInfo
->Class
)
96 case AML_CLASS_PREFIX
:
98 * Starts with a valid prefix or ASCII char, this is a name
99 * string. Convert the bare name string to a namepath.
101 WalkState
->Opcode
= AML_INT_NAMEPATH_OP
;
102 WalkState
->ArgTypes
= ARGP_NAMESTRING
;
105 case AML_CLASS_UNKNOWN
:
107 /* The opcode is unrecognized. Complain and skip unknown opcodes */
109 if (WalkState
->PassNumber
== 2)
111 AmlOffset
= (UINT32
) ACPI_PTR_DIFF (WalkState
->Aml
,
112 WalkState
->ParserState
.AmlStart
);
114 ACPI_ERROR ((AE_INFO
,
115 "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring",
117 (UINT32
) (AmlOffset
+ sizeof (ACPI_TABLE_HEADER
))));
119 ACPI_DUMP_BUFFER ((WalkState
->ParserState
.Aml
- 16), 48);
121 #ifdef ACPI_ASL_COMPILER
123 * This is executed for the disassembler only. Output goes
124 * to the disassembled ASL output file.
127 "/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n",
129 (UINT32
) (AmlOffset
+ sizeof (ACPI_TABLE_HEADER
)));
131 /* Dump the context surrounding the invalid opcode */
133 AcpiUtDumpBuffer (((UINT8
*) WalkState
->ParserState
.Aml
- 16),
135 (AmlOffset
+ sizeof (ACPI_TABLE_HEADER
) - 16));
136 AcpiOsPrintf (" */\n");
140 /* Increment past one-byte or two-byte opcode */
142 WalkState
->ParserState
.Aml
++;
143 if (WalkState
->Opcode
> 0xFF) /* Can only happen if first byte is 0x5B */
145 WalkState
->ParserState
.Aml
++;
148 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE
);
152 /* Found opcode info, this is a normal opcode */
154 WalkState
->ParserState
.Aml
+=
155 AcpiPsGetOpcodeSize (WalkState
->Opcode
);
156 WalkState
->ArgTypes
= WalkState
->OpInfo
->ParseArgs
;
160 return_ACPI_STATUS (AE_OK
);
164 /*******************************************************************************
166 * FUNCTION: AcpiPsBuildNamedOp
168 * PARAMETERS: WalkState - Current state
169 * AmlOpStart - Begin of named Op in AML
170 * UnnamedOp - Early Op (not a named Op)
175 * DESCRIPTION: Parse a named Op
177 ******************************************************************************/
181 ACPI_WALK_STATE
*WalkState
,
183 ACPI_PARSE_OBJECT
*UnnamedOp
,
184 ACPI_PARSE_OBJECT
**Op
)
186 ACPI_STATUS Status
= AE_OK
;
187 ACPI_PARSE_OBJECT
*Arg
= NULL
;
190 ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp
, WalkState
);
193 UnnamedOp
->Common
.Value
.Arg
= NULL
;
194 UnnamedOp
->Common
.ArgListLength
= 0;
195 UnnamedOp
->Common
.AmlOpcode
= WalkState
->Opcode
;
198 * Get and append arguments until we find the node that contains
199 * the name (the type ARGP_NAME).
201 while (GET_CURRENT_ARG_TYPE (WalkState
->ArgTypes
) &&
202 (GET_CURRENT_ARG_TYPE (WalkState
->ArgTypes
) != ARGP_NAME
))
204 Status
= AcpiPsGetNextArg (WalkState
, &(WalkState
->ParserState
),
205 GET_CURRENT_ARG_TYPE (WalkState
->ArgTypes
), &Arg
);
206 if (ACPI_FAILURE (Status
))
208 return_ACPI_STATUS (Status
);
211 AcpiPsAppendArg (UnnamedOp
, Arg
);
212 INCREMENT_ARG_LIST (WalkState
->ArgTypes
);
216 * Make sure that we found a NAME and didn't run out of arguments
218 if (!GET_CURRENT_ARG_TYPE (WalkState
->ArgTypes
))
220 return_ACPI_STATUS (AE_AML_NO_OPERAND
);
223 /* We know that this arg is a name, move to next arg */
225 INCREMENT_ARG_LIST (WalkState
->ArgTypes
);
228 * Find the object. This will either insert the object into
229 * the namespace or simply look it up
231 WalkState
->Op
= NULL
;
233 Status
= WalkState
->DescendingCallback (WalkState
, Op
);
234 if (ACPI_FAILURE (Status
))
236 if (Status
!= AE_CTRL_TERMINATE
)
238 ACPI_EXCEPTION ((AE_INFO
, Status
, "During name lookup/catalog"));
240 return_ACPI_STATUS (Status
);
245 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE
);
248 Status
= AcpiPsNextParseState (WalkState
, *Op
, Status
);
249 if (ACPI_FAILURE (Status
))
251 if (Status
== AE_CTRL_PENDING
)
253 Status
= AE_CTRL_PARSE_PENDING
;
255 return_ACPI_STATUS (Status
);
258 AcpiPsAppendArg (*Op
, UnnamedOp
->Common
.Value
.Arg
);
260 if ((*Op
)->Common
.AmlOpcode
== AML_REGION_OP
||
261 (*Op
)->Common
.AmlOpcode
== AML_DATA_REGION_OP
)
264 * Defer final parsing of an OperationRegion body, because we don't
265 * have enough info in the first pass to parse it correctly (i.e.,
266 * there may be method calls within the TermArg elements of the body.)
268 * However, we must continue parsing because the opregion is not a
269 * standalone package -- we don't know where the end is at this point.
271 * (Length is unknown until parse of the body complete)
273 (*Op
)->Named
.Data
= AmlOpStart
;
274 (*Op
)->Named
.Length
= 0;
277 return_ACPI_STATUS (AE_OK
);
281 /*******************************************************************************
283 * FUNCTION: AcpiPsCreateOp
285 * PARAMETERS: WalkState - Current state
286 * AmlOpStart - Op start in AML
287 * NewOp - Returned Op
291 * DESCRIPTION: Get Op from AML
293 ******************************************************************************/
297 ACPI_WALK_STATE
*WalkState
,
299 ACPI_PARSE_OBJECT
**NewOp
)
301 ACPI_STATUS Status
= AE_OK
;
302 ACPI_PARSE_OBJECT
*Op
;
303 ACPI_PARSE_OBJECT
*NamedOp
= NULL
;
304 ACPI_PARSE_OBJECT
*ParentScope
;
306 const ACPI_OPCODE_INFO
*OpInfo
;
309 ACPI_FUNCTION_TRACE_PTR (PsCreateOp
, WalkState
);
312 Status
= AcpiPsGetAmlOpcode (WalkState
);
313 if (Status
== AE_CTRL_PARSE_CONTINUE
)
315 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE
);
318 /* Create Op structure and append to parent's argument list */
320 WalkState
->OpInfo
= AcpiPsGetOpcodeInfo (WalkState
->Opcode
);
321 Op
= AcpiPsAllocOp (WalkState
->Opcode
, AmlOpStart
);
324 return_ACPI_STATUS (AE_NO_MEMORY
);
327 if (WalkState
->OpInfo
->Flags
& AML_NAMED
)
329 Status
= AcpiPsBuildNamedOp (WalkState
, AmlOpStart
, Op
, &NamedOp
);
331 if (ACPI_FAILURE (Status
))
333 return_ACPI_STATUS (Status
);
337 return_ACPI_STATUS (AE_OK
);
340 /* Not a named opcode, just allocate Op and append to parent */
342 if (WalkState
->OpInfo
->Flags
& AML_CREATE
)
345 * Backup to beginning of CreateXXXfield declaration
346 * BodyLength is unknown until we parse the body
348 Op
->Named
.Data
= AmlOpStart
;
349 Op
->Named
.Length
= 0;
352 if (WalkState
->Opcode
== AML_BANK_FIELD_OP
)
355 * Backup to beginning of BankField declaration
356 * BodyLength is unknown until we parse the body
358 Op
->Named
.Data
= AmlOpStart
;
359 Op
->Named
.Length
= 0;
362 ParentScope
= AcpiPsGetParentScope (&(WalkState
->ParserState
));
363 AcpiPsAppendArg (ParentScope
, Op
);
367 OpInfo
= AcpiPsGetOpcodeInfo (ParentScope
->Common
.AmlOpcode
);
368 if (OpInfo
->Flags
& AML_HAS_TARGET
)
370 ArgumentCount
= AcpiPsGetArgumentCount (OpInfo
->Type
);
371 if (ParentScope
->Common
.ArgListLength
> ArgumentCount
)
373 Op
->Common
.Flags
|= ACPI_PARSEOP_TARGET
;
376 else if (ParentScope
->Common
.AmlOpcode
== AML_INCREMENT_OP
)
378 Op
->Common
.Flags
|= ACPI_PARSEOP_TARGET
;
382 if (WalkState
->DescendingCallback
!= NULL
)
385 * Find the object. This will either insert the object into
386 * the namespace or simply look it up
388 WalkState
->Op
= *NewOp
= Op
;
390 Status
= WalkState
->DescendingCallback (WalkState
, &Op
);
391 Status
= AcpiPsNextParseState (WalkState
, Op
, Status
);
392 if (Status
== AE_CTRL_PENDING
)
394 Status
= AE_CTRL_PARSE_PENDING
;
398 return_ACPI_STATUS (Status
);
402 /*******************************************************************************
404 * FUNCTION: AcpiPsCompleteOp
406 * PARAMETERS: WalkState - Current state
408 * Status - Parse status before complete Op
412 * DESCRIPTION: Complete Op
414 ******************************************************************************/
418 ACPI_WALK_STATE
*WalkState
,
419 ACPI_PARSE_OBJECT
**Op
,
425 ACPI_FUNCTION_TRACE_PTR (PsCompleteOp
, WalkState
);
429 * Finished one argument of the containing scope
431 WalkState
->ParserState
.Scope
->ParseScope
.ArgCount
--;
433 /* Close this Op (will result in parse subtree deletion) */
435 Status2
= AcpiPsCompleteThisOp (WalkState
, *Op
);
436 if (ACPI_FAILURE (Status2
))
438 return_ACPI_STATUS (Status2
);
449 case AE_CTRL_TRANSFER
:
451 /* We are about to transfer to a called method */
453 WalkState
->PrevOp
= NULL
;
454 WalkState
->PrevArgTypes
= WalkState
->ArgTypes
;
455 return_ACPI_STATUS (Status
);
459 AcpiPsPopScope (&(WalkState
->ParserState
), Op
,
460 &WalkState
->ArgTypes
, &WalkState
->ArgCount
);
465 WalkState
->OpInfo
= AcpiPsGetOpcodeInfo ((*Op
)->Common
.AmlOpcode
);
466 WalkState
->Opcode
= (*Op
)->Common
.AmlOpcode
;
468 Status
= WalkState
->AscendingCallback (WalkState
);
469 Status
= AcpiPsNextParseState (WalkState
, *Op
, Status
);
471 Status2
= AcpiPsCompleteThisOp (WalkState
, *Op
);
472 if (ACPI_FAILURE (Status2
))
474 return_ACPI_STATUS (Status2
);
482 case AE_CTRL_CONTINUE
:
484 /* Pop off scopes until we find the While */
486 while (!(*Op
) || ((*Op
)->Common
.AmlOpcode
!= AML_WHILE_OP
))
488 AcpiPsPopScope (&(WalkState
->ParserState
), Op
,
489 &WalkState
->ArgTypes
, &WalkState
->ArgCount
);
492 /* Close this iteration of the While loop */
495 WalkState
->OpInfo
= AcpiPsGetOpcodeInfo ((*Op
)->Common
.AmlOpcode
);
496 WalkState
->Opcode
= (*Op
)->Common
.AmlOpcode
;
498 Status
= WalkState
->AscendingCallback (WalkState
);
499 Status
= AcpiPsNextParseState (WalkState
, *Op
, Status
);
501 Status2
= AcpiPsCompleteThisOp (WalkState
, *Op
);
502 if (ACPI_FAILURE (Status2
))
504 return_ACPI_STATUS (Status2
);
510 case AE_CTRL_TERMINATE
:
517 Status2
= AcpiPsCompleteThisOp (WalkState
, *Op
);
518 if (ACPI_FAILURE (Status2
))
520 return_ACPI_STATUS (Status2
);
523 AcpiUtDeleteGenericState (
524 AcpiUtPopGenericState (&WalkState
->ControlState
));
527 AcpiPsPopScope (&(WalkState
->ParserState
), Op
,
528 &WalkState
->ArgTypes
, &WalkState
->ArgCount
);
532 return_ACPI_STATUS (AE_OK
);
534 default: /* All other non-AE_OK status */
540 Status2
= AcpiPsCompleteThisOp (WalkState
, *Op
);
541 if (ACPI_FAILURE (Status2
))
543 return_ACPI_STATUS (Status2
);
547 AcpiPsPopScope (&(WalkState
->ParserState
), Op
,
548 &WalkState
->ArgTypes
, &WalkState
->ArgCount
);
555 * TBD: Cleanup parse ops on error
559 AcpiPsPopScope (ParserState
, Op
,
560 &WalkState
->ArgTypes
, &WalkState
->ArgCount
);
563 WalkState
->PrevOp
= NULL
;
564 WalkState
->PrevArgTypes
= WalkState
->ArgTypes
;
565 return_ACPI_STATUS (Status
);
568 /* This scope complete? */
570 if (AcpiPsHasCompletedScope (&(WalkState
->ParserState
)))
572 AcpiPsPopScope (&(WalkState
->ParserState
), Op
,
573 &WalkState
->ArgTypes
, &WalkState
->ArgCount
);
574 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE
, "Popped scope, Op=%p\n", *Op
));
581 return_ACPI_STATUS (AE_OK
);
585 /*******************************************************************************
587 * FUNCTION: AcpiPsCompleteFinalOp
589 * PARAMETERS: WalkState - Current state
591 * Status - Current parse status before complete last
596 * DESCRIPTION: Complete last Op.
598 ******************************************************************************/
601 AcpiPsCompleteFinalOp (
602 ACPI_WALK_STATE
*WalkState
,
603 ACPI_PARSE_OBJECT
*Op
,
609 ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp
, WalkState
);
613 * Complete the last Op (if not completed), and clear the scope stack.
614 * It is easily possible to end an AML "package" with an unbounded number
615 * of open scopes (such as when several ASL blocks are closed with
616 * sequential closing braces). We want to terminate each one cleanly.
618 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE
, "AML package complete at Op %p\n", Op
));
623 if (WalkState
->AscendingCallback
!= NULL
)
626 WalkState
->OpInfo
= AcpiPsGetOpcodeInfo (Op
->Common
.AmlOpcode
);
627 WalkState
->Opcode
= Op
->Common
.AmlOpcode
;
629 Status
= WalkState
->AscendingCallback (WalkState
);
630 Status
= AcpiPsNextParseState (WalkState
, Op
, Status
);
631 if (Status
== AE_CTRL_PENDING
)
633 Status
= AcpiPsCompleteOp (WalkState
, &Op
, AE_OK
);
634 if (ACPI_FAILURE (Status
))
636 return_ACPI_STATUS (Status
);
640 if (Status
== AE_CTRL_TERMINATE
)
649 Status2
= AcpiPsCompleteThisOp (WalkState
, Op
);
650 if (ACPI_FAILURE (Status2
))
652 return_ACPI_STATUS (Status2
);
656 AcpiPsPopScope (&(WalkState
->ParserState
), &Op
,
657 &WalkState
->ArgTypes
, &WalkState
->ArgCount
);
661 return_ACPI_STATUS (Status
);
664 else if (ACPI_FAILURE (Status
))
666 /* First error is most important */
668 (void) AcpiPsCompleteThisOp (WalkState
, Op
);
669 return_ACPI_STATUS (Status
);
673 Status2
= AcpiPsCompleteThisOp (WalkState
, Op
);
674 if (ACPI_FAILURE (Status2
))
676 return_ACPI_STATUS (Status2
);
680 AcpiPsPopScope (&(WalkState
->ParserState
), &Op
, &WalkState
->ArgTypes
,
681 &WalkState
->ArgCount
);
685 return_ACPI_STATUS (Status
);