]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/contrib/dev/acpica/components/parser/psobject.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / contrib / dev / acpica / components / parser / psobject.c
1 /******************************************************************************
2  *
3  * Module Name: psobject - Support for parse objects
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2015, 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 #include <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/accommon.h>
46 #include <contrib/dev/acpica/include/acparser.h>
47 #include <contrib/dev/acpica/include/amlcode.h>
48
49 #define _COMPONENT          ACPI_PARSER
50         ACPI_MODULE_NAME    ("psobject")
51
52
53 /* Local prototypes */
54
55 static ACPI_STATUS
56 AcpiPsGetAmlOpcode (
57     ACPI_WALK_STATE         *WalkState);
58
59
60 /*******************************************************************************
61  *
62  * FUNCTION:    AcpiPsGetAmlOpcode
63  *
64  * PARAMETERS:  WalkState           - Current state
65  *
66  * RETURN:      Status
67  *
68  * DESCRIPTION: Extract the next AML opcode from the input stream.
69  *
70  ******************************************************************************/
71
72 static ACPI_STATUS
73 AcpiPsGetAmlOpcode (
74     ACPI_WALK_STATE         *WalkState)
75 {
76
77     ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState);
78
79
80     WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml,
81                                 WalkState->ParserState.AmlStart);
82     WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState));
83
84     /*
85      * First cut to determine what we have found:
86      * 1) A valid AML opcode
87      * 2) A name string
88      * 3) An unknown/invalid opcode
89      */
90     WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
91
92     switch (WalkState->OpInfo->Class)
93     {
94     case AML_CLASS_ASCII:
95     case AML_CLASS_PREFIX:
96         /*
97          * Starts with a valid prefix or ASCII char, this is a name
98          * string. Convert the bare name string to a namepath.
99          */
100         WalkState->Opcode = AML_INT_NAMEPATH_OP;
101         WalkState->ArgTypes = ARGP_NAMESTRING;
102         break;
103
104     case AML_CLASS_UNKNOWN:
105
106         /* The opcode is unrecognized. Complain and skip unknown opcodes */
107
108         if (WalkState->PassNumber == 2)
109         {
110             ACPI_ERROR ((AE_INFO,
111                 "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring",
112                 WalkState->Opcode,
113                 (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER))));
114
115             ACPI_DUMP_BUFFER ((WalkState->ParserState.Aml - 16), 48);
116
117 #ifdef ACPI_ASL_COMPILER
118             /*
119              * This is executed for the disassembler only. Output goes
120              * to the disassembled ASL output file.
121              */
122             AcpiOsPrintf (
123                 "/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n",
124                 WalkState->Opcode,
125                 (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER)));
126
127             /* Dump the context surrounding the invalid opcode */
128
129             AcpiUtDumpBuffer (((UINT8 *) WalkState->ParserState.Aml - 16),
130                 48, DB_BYTE_DISPLAY,
131                 (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER) - 16));
132             AcpiOsPrintf (" */\n");
133 #endif
134         }
135
136         /* Increment past one-byte or two-byte opcode */
137
138         WalkState->ParserState.Aml++;
139         if (WalkState->Opcode > 0xFF) /* Can only happen if first byte is 0x5B */
140         {
141             WalkState->ParserState.Aml++;
142         }
143
144         return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
145
146     default:
147
148         /* Found opcode info, this is a normal opcode */
149
150         WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode);
151         WalkState->ArgTypes = WalkState->OpInfo->ParseArgs;
152         break;
153     }
154
155     return_ACPI_STATUS (AE_OK);
156 }
157
158
159 /*******************************************************************************
160  *
161  * FUNCTION:    AcpiPsBuildNamedOp
162  *
163  * PARAMETERS:  WalkState           - Current state
164  *              AmlOpStart          - Begin of named Op in AML
165  *              UnnamedOp           - Early Op (not a named Op)
166  *              Op                  - Returned Op
167  *
168  * RETURN:      Status
169  *
170  * DESCRIPTION: Parse a named Op
171  *
172  ******************************************************************************/
173
174 ACPI_STATUS
175 AcpiPsBuildNamedOp (
176     ACPI_WALK_STATE         *WalkState,
177     UINT8                   *AmlOpStart,
178     ACPI_PARSE_OBJECT       *UnnamedOp,
179     ACPI_PARSE_OBJECT       **Op)
180 {
181     ACPI_STATUS             Status = AE_OK;
182     ACPI_PARSE_OBJECT       *Arg = NULL;
183
184
185     ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState);
186
187
188     UnnamedOp->Common.Value.Arg = NULL;
189     UnnamedOp->Common.ArgListLength = 0;
190     UnnamedOp->Common.AmlOpcode = WalkState->Opcode;
191
192     /*
193      * Get and append arguments until we find the node that contains
194      * the name (the type ARGP_NAME).
195      */
196     while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
197           (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME))
198     {
199         Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState),
200                     GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
201         if (ACPI_FAILURE (Status))
202         {
203             return_ACPI_STATUS (Status);
204         }
205
206         AcpiPsAppendArg (UnnamedOp, Arg);
207         INCREMENT_ARG_LIST (WalkState->ArgTypes);
208     }
209
210     /*
211      * Make sure that we found a NAME and didn't run out of arguments
212      */
213     if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes))
214     {
215         return_ACPI_STATUS (AE_AML_NO_OPERAND);
216     }
217
218     /* We know that this arg is a name, move to next arg */
219
220     INCREMENT_ARG_LIST (WalkState->ArgTypes);
221
222     /*
223      * Find the object. This will either insert the object into
224      * the namespace or simply look it up
225      */
226     WalkState->Op = NULL;
227
228     Status = WalkState->DescendingCallback (WalkState, Op);
229     if (ACPI_FAILURE (Status))
230     {
231         if (Status != AE_CTRL_TERMINATE)
232         {
233             ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog"));
234         }
235         return_ACPI_STATUS (Status);
236     }
237
238     if (!*Op)
239     {
240         return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
241     }
242
243     Status = AcpiPsNextParseState (WalkState, *Op, Status);
244     if (ACPI_FAILURE (Status))
245     {
246         if (Status == AE_CTRL_PENDING)
247         {
248             Status = AE_CTRL_PARSE_PENDING;
249         }
250         return_ACPI_STATUS (Status);
251     }
252
253     AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg);
254
255     if ((*Op)->Common.AmlOpcode == AML_REGION_OP ||
256         (*Op)->Common.AmlOpcode == AML_DATA_REGION_OP)
257     {
258         /*
259          * Defer final parsing of an OperationRegion body, because we don't
260          * have enough info in the first pass to parse it correctly (i.e.,
261          * there may be method calls within the TermArg elements of the body.)
262          *
263          * However, we must continue parsing because the opregion is not a
264          * standalone package -- we don't know where the end is at this point.
265          *
266          * (Length is unknown until parse of the body complete)
267          */
268         (*Op)->Named.Data = AmlOpStart;
269         (*Op)->Named.Length = 0;
270     }
271
272     return_ACPI_STATUS (AE_OK);
273 }
274
275
276 /*******************************************************************************
277  *
278  * FUNCTION:    AcpiPsCreateOp
279  *
280  * PARAMETERS:  WalkState           - Current state
281  *              AmlOpStart          - Op start in AML
282  *              NewOp               - Returned Op
283  *
284  * RETURN:      Status
285  *
286  * DESCRIPTION: Get Op from AML
287  *
288  ******************************************************************************/
289
290 ACPI_STATUS
291 AcpiPsCreateOp (
292     ACPI_WALK_STATE         *WalkState,
293     UINT8                   *AmlOpStart,
294     ACPI_PARSE_OBJECT       **NewOp)
295 {
296     ACPI_STATUS             Status = AE_OK;
297     ACPI_PARSE_OBJECT       *Op;
298     ACPI_PARSE_OBJECT       *NamedOp = NULL;
299     ACPI_PARSE_OBJECT       *ParentScope;
300     UINT8                   ArgumentCount;
301     const ACPI_OPCODE_INFO  *OpInfo;
302
303
304     ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState);
305
306
307     Status = AcpiPsGetAmlOpcode (WalkState);
308     if (Status == AE_CTRL_PARSE_CONTINUE)
309     {
310         return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
311     }
312
313     /* Create Op structure and append to parent's argument list */
314
315     WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
316     Op = AcpiPsAllocOp (WalkState->Opcode);
317     if (!Op)
318     {
319         return_ACPI_STATUS (AE_NO_MEMORY);
320     }
321
322     if (WalkState->OpInfo->Flags & AML_NAMED)
323     {
324         Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp);
325         AcpiPsFreeOp (Op);
326         if (ACPI_FAILURE (Status))
327         {
328             return_ACPI_STATUS (Status);
329         }
330
331         *NewOp = NamedOp;
332         return_ACPI_STATUS (AE_OK);
333     }
334
335     /* Not a named opcode, just allocate Op and append to parent */
336
337     if (WalkState->OpInfo->Flags & AML_CREATE)
338     {
339         /*
340          * Backup to beginning of CreateXXXfield declaration
341          * BodyLength is unknown until we parse the body
342          */
343         Op->Named.Data = AmlOpStart;
344         Op->Named.Length = 0;
345     }
346
347     if (WalkState->Opcode == AML_BANK_FIELD_OP)
348     {
349         /*
350          * Backup to beginning of BankField declaration
351          * BodyLength is unknown until we parse the body
352          */
353         Op->Named.Data = AmlOpStart;
354         Op->Named.Length = 0;
355     }
356
357     ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState));
358     AcpiPsAppendArg (ParentScope, Op);
359
360     if (ParentScope)
361     {
362         OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode);
363         if (OpInfo->Flags & AML_HAS_TARGET)
364         {
365             ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type);
366             if (ParentScope->Common.ArgListLength > ArgumentCount)
367             {
368                 Op->Common.Flags |= ACPI_PARSEOP_TARGET;
369             }
370         }
371         else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP)
372         {
373             Op->Common.Flags |= ACPI_PARSEOP_TARGET;
374         }
375     }
376
377     if (WalkState->DescendingCallback != NULL)
378     {
379         /*
380          * Find the object. This will either insert the object into
381          * the namespace or simply look it up
382          */
383         WalkState->Op = *NewOp = Op;
384
385         Status = WalkState->DescendingCallback (WalkState, &Op);
386         Status = AcpiPsNextParseState (WalkState, Op, Status);
387         if (Status == AE_CTRL_PENDING)
388         {
389             Status = AE_CTRL_PARSE_PENDING;
390         }
391     }
392
393     return_ACPI_STATUS (Status);
394 }
395
396
397 /*******************************************************************************
398  *
399  * FUNCTION:    AcpiPsCompleteOp
400  *
401  * PARAMETERS:  WalkState           - Current state
402  *              Op                  - Returned Op
403  *              Status              - Parse status before complete Op
404  *
405  * RETURN:      Status
406  *
407  * DESCRIPTION: Complete Op
408  *
409  ******************************************************************************/
410
411 ACPI_STATUS
412 AcpiPsCompleteOp (
413     ACPI_WALK_STATE         *WalkState,
414     ACPI_PARSE_OBJECT       **Op,
415     ACPI_STATUS             Status)
416 {
417     ACPI_STATUS             Status2;
418
419
420     ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState);
421
422
423     /*
424      * Finished one argument of the containing scope
425      */
426     WalkState->ParserState.Scope->ParseScope.ArgCount--;
427
428     /* Close this Op (will result in parse subtree deletion) */
429
430     Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
431     if (ACPI_FAILURE (Status2))
432     {
433         return_ACPI_STATUS (Status2);
434     }
435
436     *Op = NULL;
437
438     switch (Status)
439     {
440     case AE_OK:
441
442         break;
443
444     case AE_CTRL_TRANSFER:
445
446         /* We are about to transfer to a called method */
447
448         WalkState->PrevOp = NULL;
449         WalkState->PrevArgTypes = WalkState->ArgTypes;
450         return_ACPI_STATUS (Status);
451
452     case AE_CTRL_END:
453
454         AcpiPsPopScope (&(WalkState->ParserState), Op,
455             &WalkState->ArgTypes, &WalkState->ArgCount);
456
457         if (*Op)
458         {
459             WalkState->Op = *Op;
460             WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
461             WalkState->Opcode = (*Op)->Common.AmlOpcode;
462
463             Status = WalkState->AscendingCallback (WalkState);
464             Status = AcpiPsNextParseState (WalkState, *Op, Status);
465
466             Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
467             if (ACPI_FAILURE (Status2))
468             {
469                 return_ACPI_STATUS (Status2);
470             }
471         }
472
473         Status = AE_OK;
474         break;
475
476     case AE_CTRL_BREAK:
477     case AE_CTRL_CONTINUE:
478
479         /* Pop off scopes until we find the While */
480
481         while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP))
482         {
483             AcpiPsPopScope (&(WalkState->ParserState), Op,
484                 &WalkState->ArgTypes, &WalkState->ArgCount);
485         }
486
487         /* Close this iteration of the While loop */
488
489         WalkState->Op = *Op;
490         WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
491         WalkState->Opcode = (*Op)->Common.AmlOpcode;
492
493         Status = WalkState->AscendingCallback (WalkState);
494         Status = AcpiPsNextParseState (WalkState, *Op, Status);
495
496         Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
497         if (ACPI_FAILURE (Status2))
498         {
499             return_ACPI_STATUS (Status2);
500         }
501
502         Status = AE_OK;
503         break;
504
505     case AE_CTRL_TERMINATE:
506
507         /* Clean up */
508         do
509         {
510             if (*Op)
511             {
512                 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
513                 if (ACPI_FAILURE (Status2))
514                 {
515                     return_ACPI_STATUS (Status2);
516                 }
517
518                 AcpiUtDeleteGenericState (
519                     AcpiUtPopGenericState (&WalkState->ControlState));
520             }
521
522             AcpiPsPopScope (&(WalkState->ParserState), Op,
523                 &WalkState->ArgTypes, &WalkState->ArgCount);
524
525         } while (*Op);
526
527         return_ACPI_STATUS (AE_OK);
528
529     default:  /* All other non-AE_OK status */
530
531         do
532         {
533             if (*Op)
534             {
535                 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
536                 if (ACPI_FAILURE (Status2))
537                 {
538                     return_ACPI_STATUS (Status2);
539                 }
540             }
541
542             AcpiPsPopScope (&(WalkState->ParserState), Op,
543                 &WalkState->ArgTypes, &WalkState->ArgCount);
544
545         } while (*Op);
546
547
548 #if 0
549         /*
550          * TBD: Cleanup parse ops on error
551          */
552         if (*Op == NULL)
553         {
554             AcpiPsPopScope (ParserState, Op,
555                 &WalkState->ArgTypes, &WalkState->ArgCount);
556         }
557 #endif
558         WalkState->PrevOp = NULL;
559         WalkState->PrevArgTypes = WalkState->ArgTypes;
560         return_ACPI_STATUS (Status);
561     }
562
563     /* This scope complete? */
564
565     if (AcpiPsHasCompletedScope (&(WalkState->ParserState)))
566     {
567         AcpiPsPopScope (&(WalkState->ParserState), Op,
568             &WalkState->ArgTypes, &WalkState->ArgCount);
569         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op));
570     }
571     else
572     {
573         *Op = NULL;
574     }
575
576     return_ACPI_STATUS (AE_OK);
577 }
578
579
580 /*******************************************************************************
581  *
582  * FUNCTION:    AcpiPsCompleteFinalOp
583  *
584  * PARAMETERS:  WalkState           - Current state
585  *              Op                  - Current Op
586  *              Status              - Current parse status before complete last
587  *                                    Op
588  *
589  * RETURN:      Status
590  *
591  * DESCRIPTION: Complete last Op.
592  *
593  ******************************************************************************/
594
595 ACPI_STATUS
596 AcpiPsCompleteFinalOp (
597     ACPI_WALK_STATE         *WalkState,
598     ACPI_PARSE_OBJECT       *Op,
599     ACPI_STATUS             Status)
600 {
601     ACPI_STATUS             Status2;
602
603
604     ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState);
605
606
607     /*
608      * Complete the last Op (if not completed), and clear the scope stack.
609      * It is easily possible to end an AML "package" with an unbounded number
610      * of open scopes (such as when several ASL blocks are closed with
611      * sequential closing braces). We want to terminate each one cleanly.
612      */
613     ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op));
614     do
615     {
616         if (Op)
617         {
618             if (WalkState->AscendingCallback != NULL)
619             {
620                 WalkState->Op = Op;
621                 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
622                 WalkState->Opcode = Op->Common.AmlOpcode;
623
624                 Status = WalkState->AscendingCallback (WalkState);
625                 Status = AcpiPsNextParseState (WalkState, Op, Status);
626                 if (Status == AE_CTRL_PENDING)
627                 {
628                     Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK);
629                     if (ACPI_FAILURE (Status))
630                     {
631                         return_ACPI_STATUS (Status);
632                     }
633                 }
634
635                 if (Status == AE_CTRL_TERMINATE)
636                 {
637                     Status = AE_OK;
638
639                     /* Clean up */
640                     do
641                     {
642                         if (Op)
643                         {
644                             Status2 = AcpiPsCompleteThisOp (WalkState, Op);
645                             if (ACPI_FAILURE (Status2))
646                             {
647                                 return_ACPI_STATUS (Status2);
648                             }
649                         }
650
651                         AcpiPsPopScope (&(WalkState->ParserState), &Op,
652                             &WalkState->ArgTypes, &WalkState->ArgCount);
653
654                     } while (Op);
655
656                     return_ACPI_STATUS (Status);
657                 }
658
659                 else if (ACPI_FAILURE (Status))
660                 {
661                     /* First error is most important */
662
663                     (void) AcpiPsCompleteThisOp (WalkState, Op);
664                     return_ACPI_STATUS (Status);
665                 }
666             }
667
668             Status2 = AcpiPsCompleteThisOp (WalkState, Op);
669             if (ACPI_FAILURE (Status2))
670             {
671                 return_ACPI_STATUS (Status2);
672             }
673         }
674
675         AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes,
676             &WalkState->ArgCount);
677
678     } while (Op);
679
680     return_ACPI_STATUS (Status);
681 }