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