xref: /reactos/drivers/bus/acpi/acpica/parser/psargs.c (revision 09dde2cf)
1 /******************************************************************************
2  *
3  * Module Name: psargs - Parse AML opcode arguments
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2022, 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 MERCHANTABILITY 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 "acpi.h"
45 #include "accommon.h"
46 #include "acparser.h"
47 #include "amlcode.h"
48 #include "acnamesp.h"
49 #include "acdispat.h"
50 #include "acconvert.h"
51 
52 #define _COMPONENT          ACPI_PARSER
53         ACPI_MODULE_NAME    ("psargs")
54 
55 /* Local prototypes */
56 
57 static UINT32
58 AcpiPsGetNextPackageLength (
59     ACPI_PARSE_STATE        *ParserState);
60 
61 static ACPI_PARSE_OBJECT *
62 AcpiPsGetNextField (
63     ACPI_PARSE_STATE        *ParserState);
64 
65 
66 /*******************************************************************************
67  *
68  * FUNCTION:    AcpiPsGetNextPackageLength
69  *
70  * PARAMETERS:  ParserState         - Current parser state object
71  *
72  * RETURN:      Decoded package length. On completion, the AML pointer points
73  *              past the length byte or bytes.
74  *
75  * DESCRIPTION: Decode and return a package length field.
76  *              Note: Largest package length is 28 bits, from ACPI specification
77  *
78  ******************************************************************************/
79 
80 static UINT32
81 AcpiPsGetNextPackageLength (
82     ACPI_PARSE_STATE        *ParserState)
83 {
84     UINT8                   *Aml = ParserState->Aml;
85     UINT32                  PackageLength = 0;
86     UINT32                  ByteCount;
87     UINT8                   ByteZeroMask = 0x3F; /* Default [0:5] */
88 
89 
90     ACPI_FUNCTION_TRACE (PsGetNextPackageLength);
91 
92 
93     /*
94      * Byte 0 bits [6:7] contain the number of additional bytes
95      * used to encode the package length, either 0,1,2, or 3
96      */
97     ByteCount = (Aml[0] >> 6);
98     ParserState->Aml += ((ACPI_SIZE) ByteCount + 1);
99 
100     /* Get bytes 3, 2, 1 as needed */
101 
102     while (ByteCount)
103     {
104         /*
105          * Final bit positions for the package length bytes:
106          *      Byte3->[20:27]
107          *      Byte2->[12:19]
108          *      Byte1->[04:11]
109          *      Byte0->[00:03]
110          */
111         PackageLength |= (Aml[ByteCount] << ((ByteCount << 3) - 4));
112 
113         ByteZeroMask = 0x0F; /* Use bits [0:3] of byte 0 */
114         ByteCount--;
115     }
116 
117     /* Byte 0 is a special case, either bits [0:3] or [0:5] are used */
118 
119     PackageLength |= (Aml[0] & ByteZeroMask);
120     return_UINT32 (PackageLength);
121 }
122 
123 
124 /*******************************************************************************
125  *
126  * FUNCTION:    AcpiPsGetNextPackageEnd
127  *
128  * PARAMETERS:  ParserState         - Current parser state object
129  *
130  * RETURN:      Pointer to end-of-package +1
131  *
132  * DESCRIPTION: Get next package length and return a pointer past the end of
133  *              the package. Consumes the package length field
134  *
135  ******************************************************************************/
136 
137 UINT8 *
138 AcpiPsGetNextPackageEnd (
139     ACPI_PARSE_STATE        *ParserState)
140 {
141     UINT8                   *Start = ParserState->Aml;
142     UINT32                  PackageLength;
143 
144 
145     ACPI_FUNCTION_TRACE (PsGetNextPackageEnd);
146 
147 
148     /* Function below updates ParserState->Aml */
149 
150     PackageLength = AcpiPsGetNextPackageLength (ParserState);
151 
152     return_PTR (Start + PackageLength); /* end of package */
153 }
154 
155 
156 /*******************************************************************************
157  *
158  * FUNCTION:    AcpiPsGetNextNamestring
159  *
160  * PARAMETERS:  ParserState         - Current parser state object
161  *
162  * RETURN:      Pointer to the start of the name string (pointer points into
163  *              the AML.
164  *
165  * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name
166  *              prefix characters. Set parser state to point past the string.
167  *              (Name is consumed from the AML.)
168  *
169  ******************************************************************************/
170 
171 char *
172 AcpiPsGetNextNamestring (
173     ACPI_PARSE_STATE        *ParserState)
174 {
175     UINT8                   *Start = ParserState->Aml;
176     UINT8                   *End = ParserState->Aml;
177 
178 
179     ACPI_FUNCTION_TRACE (PsGetNextNamestring);
180 
181 
182     /* Point past any namestring prefix characters (backslash or carat) */
183 
184     while (ACPI_IS_ROOT_PREFIX (*End) ||
185            ACPI_IS_PARENT_PREFIX (*End))
186     {
187         End++;
188     }
189 
190     /* Decode the path prefix character */
191 
192     switch (*End)
193     {
194     case 0:
195 
196         /* NullName */
197 
198         if (End == Start)
199         {
200             Start = NULL;
201         }
202         End++;
203         break;
204 
205     case AML_DUAL_NAME_PREFIX:
206 
207         /* Two name segments */
208 
209         End += 1 + (2 * ACPI_NAMESEG_SIZE);
210         break;
211 
212     case AML_MULTI_NAME_PREFIX:
213 
214         /* Multiple name segments, 4 chars each, count in next byte */
215 
216         End += 2 + (*(End + 1) * ACPI_NAMESEG_SIZE);
217         break;
218 
219     default:
220 
221         /* Single name segment */
222 
223         End += ACPI_NAMESEG_SIZE;
224         break;
225     }
226 
227     ParserState->Aml = End;
228     return_PTR ((char *) Start);
229 }
230 
231 
232 /*******************************************************************************
233  *
234  * FUNCTION:    AcpiPsGetNextNamepath
235  *
236  * PARAMETERS:  ParserState         - Current parser state object
237  *              Arg                 - Where the namepath will be stored
238  *              ArgCount            - If the namepath points to a control method
239  *                                    the method's argument is returned here.
240  *              PossibleMethodCall  - Whether the namepath can possibly be the
241  *                                    start of a method call
242  *
243  * RETURN:      Status
244  *
245  * DESCRIPTION: Get next name (if method call, return # of required args).
246  *              Names are looked up in the internal namespace to determine
247  *              if the name represents a control method. If a method
248  *              is found, the number of arguments to the method is returned.
249  *              This information is critical for parsing to continue correctly.
250  *
251  ******************************************************************************/
252 
253 ACPI_STATUS
254 AcpiPsGetNextNamepath (
255     ACPI_WALK_STATE         *WalkState,
256     ACPI_PARSE_STATE        *ParserState,
257     ACPI_PARSE_OBJECT       *Arg,
258     BOOLEAN                 PossibleMethodCall)
259 {
260     ACPI_STATUS             Status;
261     char                    *Path;
262     ACPI_PARSE_OBJECT       *NameOp;
263     ACPI_OPERAND_OBJECT     *MethodDesc;
264     ACPI_NAMESPACE_NODE     *Node;
265     UINT8                   *Start = ParserState->Aml;
266 
267 
268     ACPI_FUNCTION_TRACE (PsGetNextNamepath);
269 
270 
271     Path = AcpiPsGetNextNamestring (ParserState);
272     AcpiPsInitOp (Arg, AML_INT_NAMEPATH_OP);
273 
274     /* Null path case is allowed, just exit */
275 
276     if (!Path)
277     {
278         Arg->Common.Value.Name = Path;
279         return_ACPI_STATUS (AE_OK);
280     }
281 
282     /*
283      * Lookup the name in the internal namespace, starting with the current
284      * scope. We don't want to add anything new to the namespace here,
285      * however, so we use MODE_EXECUTE.
286      * Allow searching of the parent tree, but don't open a new scope -
287      * we just want to lookup the object (must be mode EXECUTE to perform
288      * the upsearch)
289      */
290     Status = AcpiNsLookup (WalkState->ScopeInfo, Path,
291         ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
292         ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, &Node);
293 
294     /*
295      * If this name is a control method invocation, we must
296      * setup the method call
297      */
298     if (ACPI_SUCCESS (Status) &&
299         PossibleMethodCall &&
300         (Node->Type == ACPI_TYPE_METHOD))
301     {
302         if ((GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) == ARGP_SUPERNAME) ||
303             (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) == ARGP_TARGET))
304         {
305             /*
306              * AcpiPsGetNextNamestring has increased the AML pointer past
307              * the method invocation namestring, so we need to restore the
308              * saved AML pointer back to the original method invocation
309              * namestring.
310              */
311             WalkState->ParserState.Aml = Start;
312             WalkState->ArgCount = 1;
313             AcpiPsInitOp (Arg, AML_INT_METHODCALL_OP);
314         }
315 
316         /* This name is actually a control method invocation */
317 
318         MethodDesc = AcpiNsGetAttachedObject (Node);
319         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
320             "Control Method invocation %4.4s - %p Desc %p Path=%p\n",
321             Node->Name.Ascii, Node, MethodDesc, Path));
322 
323         NameOp = AcpiPsAllocOp (AML_INT_NAMEPATH_OP, Start);
324         if (!NameOp)
325         {
326             return_ACPI_STATUS (AE_NO_MEMORY);
327         }
328 
329         /* Change Arg into a METHOD CALL and attach name to it */
330 
331         AcpiPsInitOp (Arg, AML_INT_METHODCALL_OP);
332         NameOp->Common.Value.Name = Path;
333 
334         /* Point METHODCALL/NAME to the METHOD Node */
335 
336         NameOp->Common.Node = Node;
337         AcpiPsAppendArg (Arg, NameOp);
338 
339         if (!MethodDesc)
340         {
341             ACPI_ERROR ((AE_INFO,
342                 "Control Method %p has no attached object",
343                 Node));
344             return_ACPI_STATUS (AE_AML_INTERNAL);
345         }
346 
347         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
348             "Control Method - %p Args %X\n",
349             Node, MethodDesc->Method.ParamCount));
350 
351         /* Get the number of arguments to expect */
352 
353         WalkState->ArgCount = MethodDesc->Method.ParamCount;
354         return_ACPI_STATUS (AE_OK);
355     }
356 
357     /*
358      * Special handling if the name was not found during the lookup -
359      * some NotFound cases are allowed
360      */
361     if (Status == AE_NOT_FOUND)
362     {
363         /* 1) NotFound is ok during load pass 1/2 (allow forward references) */
364 
365         if ((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) !=
366             ACPI_PARSE_EXECUTE)
367         {
368             Status = AE_OK;
369         }
370 
371         /* 2) NotFound during a CondRefOf(x) is ok by definition */
372 
373         else if (WalkState->Op->Common.AmlOpcode == AML_CONDITIONAL_REF_OF_OP)
374         {
375             Status = AE_OK;
376         }
377 
378         /*
379          * 3) NotFound while building a Package is ok at this point, we
380          * may flag as an error later if slack mode is not enabled.
381          * (Some ASL code depends on allowing this behavior)
382          */
383         else if ((Arg->Common.Parent) &&
384             ((Arg->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
385              (Arg->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)))
386         {
387             Status = AE_OK;
388         }
389     }
390 
391     /* Final exception check (may have been changed from code above) */
392 
393     if (ACPI_FAILURE (Status))
394     {
395         ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo, Path, Status);
396 
397         if ((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) ==
398             ACPI_PARSE_EXECUTE)
399         {
400             /* Report a control method execution error */
401 
402             Status = AcpiDsMethodError (Status, WalkState);
403         }
404     }
405 
406     /* Save the namepath */
407 
408     Arg->Common.Value.Name = Path;
409     return_ACPI_STATUS (Status);
410 }
411 
412 
413 /*******************************************************************************
414  *
415  * FUNCTION:    AcpiPsGetNextSimpleArg
416  *
417  * PARAMETERS:  ParserState         - Current parser state object
418  *              ArgType             - The argument type (AML_*_ARG)
419  *              Arg                 - Where the argument is returned
420  *
421  * RETURN:      None
422  *
423  * DESCRIPTION: Get the next simple argument (constant, string, or namestring)
424  *
425  ******************************************************************************/
426 
427 void
428 AcpiPsGetNextSimpleArg (
429     ACPI_PARSE_STATE        *ParserState,
430     UINT32                  ArgType,
431     ACPI_PARSE_OBJECT       *Arg)
432 {
433     UINT32                  Length;
434     UINT16                  Opcode;
435     UINT8                   *Aml = ParserState->Aml;
436 
437 
438     ACPI_FUNCTION_TRACE_U32 (PsGetNextSimpleArg, ArgType);
439 
440 
441     switch (ArgType)
442     {
443     case ARGP_BYTEDATA:
444 
445         /* Get 1 byte from the AML stream */
446 
447         Opcode = AML_BYTE_OP;
448         Arg->Common.Value.Integer = (UINT64) *Aml;
449         Length = 1;
450         break;
451 
452     case ARGP_WORDDATA:
453 
454         /* Get 2 bytes from the AML stream */
455 
456         Opcode = AML_WORD_OP;
457         ACPI_MOVE_16_TO_64 (&Arg->Common.Value.Integer, Aml);
458         Length = 2;
459         break;
460 
461     case ARGP_DWORDDATA:
462 
463         /* Get 4 bytes from the AML stream */
464 
465         Opcode = AML_DWORD_OP;
466         ACPI_MOVE_32_TO_64 (&Arg->Common.Value.Integer, Aml);
467         Length = 4;
468         break;
469 
470     case ARGP_QWORDDATA:
471 
472         /* Get 8 bytes from the AML stream */
473 
474         Opcode = AML_QWORD_OP;
475         ACPI_MOVE_64_TO_64 (&Arg->Common.Value.Integer, Aml);
476         Length = 8;
477         break;
478 
479     case ARGP_CHARLIST:
480 
481         /* Get a pointer to the string, point past the string */
482 
483         Opcode = AML_STRING_OP;
484         Arg->Common.Value.String = ACPI_CAST_PTR (char, Aml);
485 
486         /* Find the null terminator */
487 
488         Length = 0;
489         while (Aml[Length])
490         {
491             Length++;
492         }
493         Length++;
494         break;
495 
496     case ARGP_NAME:
497     case ARGP_NAMESTRING:
498 
499         AcpiPsInitOp (Arg, AML_INT_NAMEPATH_OP);
500         Arg->Common.Value.Name = AcpiPsGetNextNamestring (ParserState);
501         return_VOID;
502 
503     default:
504 
505         ACPI_ERROR ((AE_INFO, "Invalid ArgType 0x%X", ArgType));
506         return_VOID;
507     }
508 
509     AcpiPsInitOp (Arg, Opcode);
510     ParserState->Aml += Length;
511     return_VOID;
512 }
513 
514 
515 /*******************************************************************************
516  *
517  * FUNCTION:    AcpiPsGetNextField
518  *
519  * PARAMETERS:  ParserState         - Current parser state object
520  *
521  * RETURN:      A newly allocated FIELD op
522  *
523  * DESCRIPTION: Get next field (NamedField, ReservedField, or AccessField)
524  *
525  ******************************************************************************/
526 
527 static ACPI_PARSE_OBJECT *
528 AcpiPsGetNextField (
529     ACPI_PARSE_STATE        *ParserState)
530 {
531     UINT8                   *Aml;
532     ACPI_PARSE_OBJECT       *Field;
533     ACPI_PARSE_OBJECT       *Arg = NULL;
534     UINT16                  Opcode;
535     UINT32                  Name;
536     UINT8                   AccessType;
537     UINT8                   AccessAttribute;
538     UINT8                   AccessLength;
539     UINT32                  PkgLength;
540     UINT8                   *PkgEnd;
541     UINT32                  BufferLength;
542 
543 
544     ACPI_FUNCTION_TRACE (PsGetNextField);
545 
546 
547     ASL_CV_CAPTURE_COMMENTS_ONLY (ParserState);
548     Aml = ParserState->Aml;
549 
550     /* Determine field type */
551 
552     switch (ACPI_GET8 (ParserState->Aml))
553     {
554     case AML_FIELD_OFFSET_OP:
555 
556         Opcode = AML_INT_RESERVEDFIELD_OP;
557         ParserState->Aml++;
558         break;
559 
560     case AML_FIELD_ACCESS_OP:
561 
562         Opcode = AML_INT_ACCESSFIELD_OP;
563         ParserState->Aml++;
564         break;
565 
566     case AML_FIELD_CONNECTION_OP:
567 
568         Opcode = AML_INT_CONNECTION_OP;
569         ParserState->Aml++;
570         break;
571 
572     case AML_FIELD_EXT_ACCESS_OP:
573 
574         Opcode = AML_INT_EXTACCESSFIELD_OP;
575         ParserState->Aml++;
576         break;
577 
578     default:
579 
580         Opcode = AML_INT_NAMEDFIELD_OP;
581         break;
582     }
583 
584     /* Allocate a new field op */
585 
586     Field = AcpiPsAllocOp (Opcode, Aml);
587     if (!Field)
588     {
589         return_PTR (NULL);
590     }
591 
592     /* Decode the field type */
593 
594     ASL_CV_CAPTURE_COMMENTS_ONLY (ParserState);
595     switch (Opcode)
596     {
597     case AML_INT_NAMEDFIELD_OP:
598 
599         /* Get the 4-character name */
600 
601         ACPI_MOVE_32_TO_32 (&Name, ParserState->Aml);
602         AcpiPsSetName (Field, Name);
603         ParserState->Aml += ACPI_NAMESEG_SIZE;
604 
605 
606         ASL_CV_CAPTURE_COMMENTS_ONLY (ParserState);
607 
608 #ifdef ACPI_ASL_COMPILER
609         /*
610          * Because the package length isn't represented as a parse tree object,
611          * take comments surrounding this and add to the previously created
612          * parse node.
613          */
614         if (Field->Common.InlineComment)
615         {
616             Field->Common.NameComment = Field->Common.InlineComment;
617         }
618         Field->Common.InlineComment  = AcpiGbl_CurrentInlineComment;
619         AcpiGbl_CurrentInlineComment = NULL;
620 #endif
621 
622         /* Get the length which is encoded as a package length */
623 
624         Field->Common.Value.Size = AcpiPsGetNextPackageLength (ParserState);
625         break;
626 
627 
628     case AML_INT_RESERVEDFIELD_OP:
629 
630         /* Get the length which is encoded as a package length */
631 
632         Field->Common.Value.Size = AcpiPsGetNextPackageLength (ParserState);
633         break;
634 
635 
636     case AML_INT_ACCESSFIELD_OP:
637     case AML_INT_EXTACCESSFIELD_OP:
638 
639         /*
640          * Get AccessType and AccessAttrib and merge into the field Op
641          * AccessType is first operand, AccessAttribute is second. stuff
642          * these bytes into the node integer value for convenience.
643          */
644 
645         /* Get the two bytes (Type/Attribute) */
646 
647         AccessType = ACPI_GET8 (ParserState->Aml);
648         ParserState->Aml++;
649         AccessAttribute = ACPI_GET8 (ParserState->Aml);
650         ParserState->Aml++;
651 
652         Field->Common.Value.Integer = (UINT8) AccessType;
653         Field->Common.Value.Integer |= (UINT16) (AccessAttribute << 8);
654 
655         /* This opcode has a third byte, AccessLength */
656 
657         if (Opcode == AML_INT_EXTACCESSFIELD_OP)
658         {
659             AccessLength = ACPI_GET8 (ParserState->Aml);
660             ParserState->Aml++;
661 
662             Field->Common.Value.Integer |= (UINT32) (AccessLength << 16);
663         }
664         break;
665 
666 
667     case AML_INT_CONNECTION_OP:
668 
669         /*
670          * Argument for Connection operator can be either a Buffer
671          * (resource descriptor), or a NameString.
672          */
673         Aml = ParserState->Aml;
674         if (ACPI_GET8 (ParserState->Aml) == AML_BUFFER_OP)
675         {
676             ParserState->Aml++;
677 
678             ASL_CV_CAPTURE_COMMENTS_ONLY (ParserState);
679             PkgEnd = ParserState->Aml;
680             PkgLength = AcpiPsGetNextPackageLength (ParserState);
681             PkgEnd += PkgLength;
682 
683             ASL_CV_CAPTURE_COMMENTS_ONLY (ParserState);
684             if (ParserState->Aml < PkgEnd)
685             {
686                 /* Non-empty list */
687 
688                 Arg = AcpiPsAllocOp (AML_INT_BYTELIST_OP, Aml);
689                 if (!Arg)
690                 {
691                     AcpiPsFreeOp (Field);
692                     return_PTR (NULL);
693                 }
694 
695                 /* Get the actual buffer length argument */
696 
697                 Opcode = ACPI_GET8 (ParserState->Aml);
698                 ParserState->Aml++;
699 
700                 ASL_CV_CAPTURE_COMMENTS_ONLY (ParserState);
701                 switch (Opcode)
702                 {
703                 case AML_BYTE_OP:       /* AML_BYTEDATA_ARG */
704 
705                     BufferLength = ACPI_GET8 (ParserState->Aml);
706                     ParserState->Aml += 1;
707                     break;
708 
709                 case AML_WORD_OP:       /* AML_WORDDATA_ARG */
710 
711                     BufferLength = ACPI_GET16 (ParserState->Aml);
712                     ParserState->Aml += 2;
713                     break;
714 
715                 case AML_DWORD_OP:      /* AML_DWORDATA_ARG */
716 
717                     BufferLength = ACPI_GET32 (ParserState->Aml);
718                     ParserState->Aml += 4;
719                     break;
720 
721                 default:
722 
723                     BufferLength = 0;
724                     break;
725                 }
726 
727                 /* Fill in bytelist data */
728 
729                 ASL_CV_CAPTURE_COMMENTS_ONLY (ParserState);
730                 Arg->Named.Value.Size = BufferLength;
731                 Arg->Named.Data = ParserState->Aml;
732             }
733 
734             /* Skip to End of byte data */
735 
736             ParserState->Aml = PkgEnd;
737         }
738         else
739         {
740             Arg = AcpiPsAllocOp (AML_INT_NAMEPATH_OP, Aml);
741             if (!Arg)
742             {
743                 AcpiPsFreeOp (Field);
744                 return_PTR (NULL);
745             }
746 
747             /* Get the Namestring argument */
748 
749             Arg->Common.Value.Name = AcpiPsGetNextNamestring (ParserState);
750         }
751 
752         /* Link the buffer/namestring to parent (CONNECTION_OP) */
753 
754         AcpiPsAppendArg (Field, Arg);
755         break;
756 
757 
758     default:
759 
760         /* Opcode was set in previous switch */
761         break;
762     }
763 
764     return_PTR (Field);
765 }
766 
767 
768 /*******************************************************************************
769  *
770  * FUNCTION:    AcpiPsGetNextArg
771  *
772  * PARAMETERS:  WalkState           - Current state
773  *              ParserState         - Current parser state object
774  *              ArgType             - The argument type (AML_*_ARG)
775  *              ReturnArg           - Where the next arg is returned
776  *
777  * RETURN:      Status, and an op object containing the next argument.
778  *
779  * DESCRIPTION: Get next argument (including complex list arguments that require
780  *              pushing the parser stack)
781  *
782  ******************************************************************************/
783 
784 ACPI_STATUS
785 AcpiPsGetNextArg (
786     ACPI_WALK_STATE         *WalkState,
787     ACPI_PARSE_STATE        *ParserState,
788     UINT32                  ArgType,
789     ACPI_PARSE_OBJECT       **ReturnArg)
790 {
791     ACPI_PARSE_OBJECT       *Arg = NULL;
792     ACPI_PARSE_OBJECT       *Prev = NULL;
793     ACPI_PARSE_OBJECT       *Field;
794     UINT32                  Subop;
795     ACPI_STATUS             Status = AE_OK;
796 
797 
798     ACPI_FUNCTION_TRACE_PTR (PsGetNextArg, ParserState);
799 
800 
801     ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
802         "Expected argument type ARGP: %s (%2.2X)\n",
803         AcpiUtGetArgumentTypeName (ArgType), ArgType));
804 
805     switch (ArgType)
806     {
807     case ARGP_BYTEDATA:
808     case ARGP_WORDDATA:
809     case ARGP_DWORDDATA:
810     case ARGP_CHARLIST:
811     case ARGP_NAME:
812     case ARGP_NAMESTRING:
813 
814         /* Constants, strings, and namestrings are all the same size */
815 
816         Arg = AcpiPsAllocOp (AML_BYTE_OP, ParserState->Aml);
817         if (!Arg)
818         {
819             return_ACPI_STATUS (AE_NO_MEMORY);
820         }
821 
822         AcpiPsGetNextSimpleArg (ParserState, ArgType, Arg);
823         break;
824 
825     case ARGP_PKGLENGTH:
826 
827         /* Package length, nothing returned */
828 
829         ParserState->PkgEnd = AcpiPsGetNextPackageEnd (ParserState);
830         break;
831 
832     case ARGP_FIELDLIST:
833 
834         if (ParserState->Aml < ParserState->PkgEnd)
835         {
836             /* Non-empty list */
837 
838             while (ParserState->Aml < ParserState->PkgEnd)
839             {
840                 Field = AcpiPsGetNextField (ParserState);
841                 if (!Field)
842                 {
843                     return_ACPI_STATUS (AE_NO_MEMORY);
844                 }
845 
846                 if (Prev)
847                 {
848                     Prev->Common.Next = Field;
849                 }
850                 else
851                 {
852                     Arg = Field;
853                 }
854                 Prev = Field;
855             }
856 
857             /* Skip to End of byte data */
858 
859             ParserState->Aml = ParserState->PkgEnd;
860         }
861         break;
862 
863     case ARGP_BYTELIST:
864 
865         if (ParserState->Aml < ParserState->PkgEnd)
866         {
867             /* Non-empty list */
868 
869             Arg = AcpiPsAllocOp (AML_INT_BYTELIST_OP,
870                 ParserState->Aml);
871             if (!Arg)
872             {
873                 return_ACPI_STATUS (AE_NO_MEMORY);
874             }
875 
876             /* Fill in bytelist data */
877 
878             Arg->Common.Value.Size = (UINT32)
879                 ACPI_PTR_DIFF (ParserState->PkgEnd, ParserState->Aml);
880             Arg->Named.Data = ParserState->Aml;
881 
882             /* Skip to End of byte data */
883 
884             ParserState->Aml = ParserState->PkgEnd;
885         }
886         break;
887 
888     case ARGP_SIMPLENAME:
889     case ARGP_NAME_OR_REF:
890 
891         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
892             "**** SimpleName/NameOrRef: %s (%2.2X)\n",
893             AcpiUtGetArgumentTypeName (ArgType), ArgType));
894 
895         Subop = AcpiPsPeekOpcode (ParserState);
896         if (Subop == 0                  ||
897             AcpiPsIsLeadingChar (Subop) ||
898             ACPI_IS_ROOT_PREFIX (Subop) ||
899             ACPI_IS_PARENT_PREFIX (Subop))
900         {
901             /* NullName or NameString */
902 
903             Arg = AcpiPsAllocOp (AML_INT_NAMEPATH_OP, ParserState->Aml);
904             if (!Arg)
905             {
906                 return_ACPI_STATUS (AE_NO_MEMORY);
907             }
908 
909             Status = AcpiPsGetNextNamepath (WalkState, ParserState,
910                 Arg, ACPI_NOT_METHOD_CALL);
911         }
912         else
913         {
914             /* Single complex argument, nothing returned */
915 
916             WalkState->ArgCount = 1;
917         }
918         break;
919 
920     case ARGP_TARGET:
921     case ARGP_SUPERNAME:
922 
923         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
924             "**** Target/Supername: %s (%2.2X)\n",
925             AcpiUtGetArgumentTypeName (ArgType), ArgType));
926 
927         Subop = AcpiPsPeekOpcode (ParserState);
928         if (Subop == 0                  ||
929             AcpiPsIsLeadingChar (Subop) ||
930             ACPI_IS_ROOT_PREFIX (Subop) ||
931             ACPI_IS_PARENT_PREFIX (Subop))
932         {
933             /* NULL target (zero). Convert to a NULL namepath */
934 
935             Arg = AcpiPsAllocOp (AML_INT_NAMEPATH_OP, ParserState->Aml);
936             if (!Arg)
937             {
938                 return_ACPI_STATUS (AE_NO_MEMORY);
939             }
940 
941             Status = AcpiPsGetNextNamepath (WalkState, ParserState,
942                 Arg, ACPI_POSSIBLE_METHOD_CALL);
943 
944             if (Arg->Common.AmlOpcode == AML_INT_METHODCALL_OP)
945             {
946                 /* Free method call op and corresponding namestring sub-ob */
947 
948                 AcpiPsFreeOp (Arg->Common.Value.Arg);
949                 AcpiPsFreeOp (Arg);
950                 Arg = NULL;
951                 WalkState->ArgCount = 1;
952             }
953         }
954         else
955         {
956             /* Single complex argument, nothing returned */
957 
958             WalkState->ArgCount = 1;
959         }
960         break;
961 
962     case ARGP_DATAOBJ:
963     case ARGP_TERMARG:
964 
965         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
966             "**** TermArg/DataObj: %s (%2.2X)\n",
967             AcpiUtGetArgumentTypeName (ArgType), ArgType));
968 
969         /* Single complex argument, nothing returned */
970 
971         WalkState->ArgCount = 1;
972         break;
973 
974     case ARGP_DATAOBJLIST:
975     case ARGP_TERMLIST:
976     case ARGP_OBJLIST:
977 
978         if (ParserState->Aml < ParserState->PkgEnd)
979         {
980             /* Non-empty list of variable arguments, nothing returned */
981 
982             WalkState->ArgCount = ACPI_VAR_ARGS;
983         }
984         break;
985 
986     default:
987 
988         ACPI_ERROR ((AE_INFO, "Invalid ArgType: 0x%X", ArgType));
989         Status = AE_AML_OPERAND_TYPE;
990         break;
991     }
992 
993     *ReturnArg = Arg;
994     return_ACPI_STATUS (Status);
995 }
996