linux/drivers/acpi/acpica/psargs.c
<<
>>
Prefs
   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#include <acpi/acpi.h>
  45#include "accommon.h"
  46#include "acparser.h"
  47#include "amlcode.h"
  48#include "acnamesp.h"
  49#include "acdispat.h"
  50
  51#define _COMPONENT          ACPI_PARSER
  52ACPI_MODULE_NAME("psargs")
  53
  54/* Local prototypes */
  55static u32
  56acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state);
  57
  58static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
  59                                                       *parser_state);
  60
  61/*******************************************************************************
  62 *
  63 * FUNCTION:    acpi_ps_get_next_package_length
  64 *
  65 * PARAMETERS:  parser_state        - Current parser state object
  66 *
  67 * RETURN:      Decoded package length. On completion, the AML pointer points
  68 *              past the length byte or bytes.
  69 *
  70 * DESCRIPTION: Decode and return a package length field.
  71 *              Note: Largest package length is 28 bits, from ACPI specification
  72 *
  73 ******************************************************************************/
  74
  75static u32
  76acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
  77{
  78        u8 *aml = parser_state->aml;
  79        u32 package_length = 0;
  80        u32 byte_count;
  81        u8 byte_zero_mask = 0x3F;       /* Default [0:5] */
  82
  83        ACPI_FUNCTION_TRACE(ps_get_next_package_length);
  84
  85        /*
  86         * Byte 0 bits [6:7] contain the number of additional bytes
  87         * used to encode the package length, either 0,1,2, or 3
  88         */
  89        byte_count = (aml[0] >> 6);
  90        parser_state->aml += ((acpi_size) byte_count + 1);
  91
  92        /* Get bytes 3, 2, 1 as needed */
  93
  94        while (byte_count) {
  95                /*
  96                 * Final bit positions for the package length bytes:
  97                 *      Byte3->[20:27]
  98                 *      Byte2->[12:19]
  99                 *      Byte1->[04:11]
 100                 *      Byte0->[00:03]
 101                 */
 102                package_length |= (aml[byte_count] << ((byte_count << 3) - 4));
 103
 104                byte_zero_mask = 0x0F;  /* Use bits [0:3] of byte 0 */
 105                byte_count--;
 106        }
 107
 108        /* Byte 0 is a special case, either bits [0:3] or [0:5] are used */
 109
 110        package_length |= (aml[0] & byte_zero_mask);
 111        return_UINT32(package_length);
 112}
 113
 114/*******************************************************************************
 115 *
 116 * FUNCTION:    acpi_ps_get_next_package_end
 117 *
 118 * PARAMETERS:  parser_state        - Current parser state object
 119 *
 120 * RETURN:      Pointer to end-of-package +1
 121 *
 122 * DESCRIPTION: Get next package length and return a pointer past the end of
 123 *              the package.  Consumes the package length field
 124 *
 125 ******************************************************************************/
 126
 127u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state)
 128{
 129        u8 *start = parser_state->aml;
 130        u32 package_length;
 131
 132        ACPI_FUNCTION_TRACE(ps_get_next_package_end);
 133
 134        /* Function below updates parser_state->Aml */
 135
 136        package_length = acpi_ps_get_next_package_length(parser_state);
 137
 138        return_PTR(start + package_length);     /* end of package */
 139}
 140
 141/*******************************************************************************
 142 *
 143 * FUNCTION:    acpi_ps_get_next_namestring
 144 *
 145 * PARAMETERS:  parser_state        - Current parser state object
 146 *
 147 * RETURN:      Pointer to the start of the name string (pointer points into
 148 *              the AML.
 149 *
 150 * DESCRIPTION: Get next raw namestring within the AML stream.  Handles all name
 151 *              prefix characters.  Set parser state to point past the string.
 152 *              (Name is consumed from the AML.)
 153 *
 154 ******************************************************************************/
 155
 156char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state)
 157{
 158        u8 *start = parser_state->aml;
 159        u8 *end = parser_state->aml;
 160
 161        ACPI_FUNCTION_TRACE(ps_get_next_namestring);
 162
 163        /* Point past any namestring prefix characters (backslash or carat) */
 164
 165        while (acpi_ps_is_prefix_char(*end)) {
 166                end++;
 167        }
 168
 169        /* Decode the path prefix character */
 170
 171        switch (*end) {
 172        case 0:
 173
 174                /* null_name */
 175
 176                if (end == start) {
 177                        start = NULL;
 178                }
 179                end++;
 180                break;
 181
 182        case AML_DUAL_NAME_PREFIX:
 183
 184                /* Two name segments */
 185
 186                end += 1 + (2 * ACPI_NAME_SIZE);
 187                break;
 188
 189        case AML_MULTI_NAME_PREFIX_OP:
 190
 191                /* Multiple name segments, 4 chars each, count in next byte */
 192
 193                end += 2 + (*(end + 1) * ACPI_NAME_SIZE);
 194                break;
 195
 196        default:
 197
 198                /* Single name segment */
 199
 200                end += ACPI_NAME_SIZE;
 201                break;
 202        }
 203
 204        parser_state->aml = end;
 205        return_PTR((char *)start);
 206}
 207
 208/*******************************************************************************
 209 *
 210 * FUNCTION:    acpi_ps_get_next_namepath
 211 *
 212 * PARAMETERS:  parser_state        - Current parser state object
 213 *              arg                 - Where the namepath will be stored
 214 *              arg_count           - If the namepath points to a control method
 215 *                                    the method's argument is returned here.
 216 *              possible_method_call - Whether the namepath can possibly be the
 217 *                                    start of a method call
 218 *
 219 * RETURN:      Status
 220 *
 221 * DESCRIPTION: Get next name (if method call, return # of required args).
 222 *              Names are looked up in the internal namespace to determine
 223 *              if the name represents a control method.  If a method
 224 *              is found, the number of arguments to the method is returned.
 225 *              This information is critical for parsing to continue correctly.
 226 *
 227 ******************************************************************************/
 228
 229acpi_status
 230acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
 231                          struct acpi_parse_state *parser_state,
 232                          union acpi_parse_object *arg, u8 possible_method_call)
 233{
 234        acpi_status status;
 235        char *path;
 236        union acpi_parse_object *name_op;
 237        union acpi_operand_object *method_desc;
 238        struct acpi_namespace_node *node;
 239        u8 *start = parser_state->aml;
 240
 241        ACPI_FUNCTION_TRACE(ps_get_next_namepath);
 242
 243        path = acpi_ps_get_next_namestring(parser_state);
 244        acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP);
 245
 246        /* Null path case is allowed, just exit */
 247
 248        if (!path) {
 249                arg->common.value.name = path;
 250                return_ACPI_STATUS(AE_OK);
 251        }
 252
 253        /*
 254         * Lookup the name in the internal namespace, starting with the current
 255         * scope. We don't want to add anything new to the namespace here,
 256         * however, so we use MODE_EXECUTE.
 257         * Allow searching of the parent tree, but don't open a new scope -
 258         * we just want to lookup the object (must be mode EXECUTE to perform
 259         * the upsearch)
 260         */
 261        status = acpi_ns_lookup(walk_state->scope_info, path,
 262                                ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
 263                                ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
 264                                NULL, &node);
 265
 266        /*
 267         * If this name is a control method invocation, we must
 268         * setup the method call
 269         */
 270        if (ACPI_SUCCESS(status) &&
 271            possible_method_call && (node->type == ACPI_TYPE_METHOD)) {
 272                if (walk_state->opcode == AML_UNLOAD_OP) {
 273                        /*
 274                         * acpi_ps_get_next_namestring has increased the AML pointer,
 275                         * so we need to restore the saved AML pointer for method call.
 276                         */
 277                        walk_state->parser_state.aml = start;
 278                        walk_state->arg_count = 1;
 279                        acpi_ps_init_op(arg, AML_INT_METHODCALL_OP);
 280                        return_ACPI_STATUS(AE_OK);
 281                }
 282
 283                /* This name is actually a control method invocation */
 284
 285                method_desc = acpi_ns_get_attached_object(node);
 286                ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 287                                  "Control Method - %p Desc %p Path=%p\n", node,
 288                                  method_desc, path));
 289
 290                name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
 291                if (!name_op) {
 292                        return_ACPI_STATUS(AE_NO_MEMORY);
 293                }
 294
 295                /* Change Arg into a METHOD CALL and attach name to it */
 296
 297                acpi_ps_init_op(arg, AML_INT_METHODCALL_OP);
 298                name_op->common.value.name = path;
 299
 300                /* Point METHODCALL/NAME to the METHOD Node */
 301
 302                name_op->common.node = node;
 303                acpi_ps_append_arg(arg, name_op);
 304
 305                if (!method_desc) {
 306                        ACPI_ERROR((AE_INFO,
 307                                    "Control Method %p has no attached object",
 308                                    node));
 309                        return_ACPI_STATUS(AE_AML_INTERNAL);
 310                }
 311
 312                ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 313                                  "Control Method - %p Args %X\n",
 314                                  node, method_desc->method.param_count));
 315
 316                /* Get the number of arguments to expect */
 317
 318                walk_state->arg_count = method_desc->method.param_count;
 319                return_ACPI_STATUS(AE_OK);
 320        }
 321
 322        /*
 323         * Special handling if the name was not found during the lookup -
 324         * some not_found cases are allowed
 325         */
 326        if (status == AE_NOT_FOUND) {
 327
 328                /* 1) not_found is ok during load pass 1/2 (allow forward references) */
 329
 330                if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) !=
 331                    ACPI_PARSE_EXECUTE) {
 332                        status = AE_OK;
 333                }
 334
 335                /* 2) not_found during a cond_ref_of(x) is ok by definition */
 336
 337                else if (walk_state->op->common.aml_opcode ==
 338                         AML_COND_REF_OF_OP) {
 339                        status = AE_OK;
 340                }
 341
 342                /*
 343                 * 3) not_found while building a Package is ok at this point, we
 344                 * may flag as an error later if slack mode is not enabled.
 345                 * (Some ASL code depends on allowing this behavior)
 346                 */
 347                else if ((arg->common.parent) &&
 348                         ((arg->common.parent->common.aml_opcode ==
 349                           AML_PACKAGE_OP)
 350                          || (arg->common.parent->common.aml_opcode ==
 351                              AML_VAR_PACKAGE_OP))) {
 352                        status = AE_OK;
 353                }
 354        }
 355
 356        /* Final exception check (may have been changed from code above) */
 357
 358        if (ACPI_FAILURE(status)) {
 359                ACPI_ERROR_NAMESPACE(path, status);
 360
 361                if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) ==
 362                    ACPI_PARSE_EXECUTE) {
 363
 364                        /* Report a control method execution error */
 365
 366                        status = acpi_ds_method_error(status, walk_state);
 367                }
 368        }
 369
 370        /* Save the namepath */
 371
 372        arg->common.value.name = path;
 373        return_ACPI_STATUS(status);
 374}
 375
 376/*******************************************************************************
 377 *
 378 * FUNCTION:    acpi_ps_get_next_simple_arg
 379 *
 380 * PARAMETERS:  parser_state        - Current parser state object
 381 *              arg_type            - The argument type (AML_*_ARG)
 382 *              arg                 - Where the argument is returned
 383 *
 384 * RETURN:      None
 385 *
 386 * DESCRIPTION: Get the next simple argument (constant, string, or namestring)
 387 *
 388 ******************************************************************************/
 389
 390void
 391acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
 392                            u32 arg_type, union acpi_parse_object *arg)
 393{
 394        u32 length;
 395        u16 opcode;
 396        u8 *aml = parser_state->aml;
 397
 398        ACPI_FUNCTION_TRACE_U32(ps_get_next_simple_arg, arg_type);
 399
 400        switch (arg_type) {
 401        case ARGP_BYTEDATA:
 402
 403                /* Get 1 byte from the AML stream */
 404
 405                opcode = AML_BYTE_OP;
 406                arg->common.value.integer = (u64) *aml;
 407                length = 1;
 408                break;
 409
 410        case ARGP_WORDDATA:
 411
 412                /* Get 2 bytes from the AML stream */
 413
 414                opcode = AML_WORD_OP;
 415                ACPI_MOVE_16_TO_64(&arg->common.value.integer, aml);
 416                length = 2;
 417                break;
 418
 419        case ARGP_DWORDDATA:
 420
 421                /* Get 4 bytes from the AML stream */
 422
 423                opcode = AML_DWORD_OP;
 424                ACPI_MOVE_32_TO_64(&arg->common.value.integer, aml);
 425                length = 4;
 426                break;
 427
 428        case ARGP_QWORDDATA:
 429
 430                /* Get 8 bytes from the AML stream */
 431
 432                opcode = AML_QWORD_OP;
 433                ACPI_MOVE_64_TO_64(&arg->common.value.integer, aml);
 434                length = 8;
 435                break;
 436
 437        case ARGP_CHARLIST:
 438
 439                /* Get a pointer to the string, point past the string */
 440
 441                opcode = AML_STRING_OP;
 442                arg->common.value.string = ACPI_CAST_PTR(char, aml);
 443
 444                /* Find the null terminator */
 445
 446                length = 0;
 447                while (aml[length]) {
 448                        length++;
 449                }
 450                length++;
 451                break;
 452
 453        case ARGP_NAME:
 454        case ARGP_NAMESTRING:
 455
 456                acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP);
 457                arg->common.value.name =
 458                    acpi_ps_get_next_namestring(parser_state);
 459                return_VOID;
 460
 461        default:
 462
 463                ACPI_ERROR((AE_INFO, "Invalid ArgType 0x%X", arg_type));
 464                return_VOID;
 465        }
 466
 467        acpi_ps_init_op(arg, opcode);
 468        parser_state->aml += length;
 469        return_VOID;
 470}
 471
 472/*******************************************************************************
 473 *
 474 * FUNCTION:    acpi_ps_get_next_field
 475 *
 476 * PARAMETERS:  parser_state        - Current parser state object
 477 *
 478 * RETURN:      A newly allocated FIELD op
 479 *
 480 * DESCRIPTION: Get next field (named_field, reserved_field, or access_field)
 481 *
 482 ******************************************************************************/
 483
 484static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
 485                                                       *parser_state)
 486{
 487        u32 aml_offset;
 488        union acpi_parse_object *field;
 489        union acpi_parse_object *arg = NULL;
 490        u16 opcode;
 491        u32 name;
 492        u8 access_type;
 493        u8 access_attribute;
 494        u8 access_length;
 495        u32 pkg_length;
 496        u8 *pkg_end;
 497        u32 buffer_length;
 498
 499        ACPI_FUNCTION_TRACE(ps_get_next_field);
 500
 501        aml_offset =
 502            (u32)ACPI_PTR_DIFF(parser_state->aml, parser_state->aml_start);
 503
 504        /* Determine field type */
 505
 506        switch (ACPI_GET8(parser_state->aml)) {
 507        case AML_FIELD_OFFSET_OP:
 508
 509                opcode = AML_INT_RESERVEDFIELD_OP;
 510                parser_state->aml++;
 511                break;
 512
 513        case AML_FIELD_ACCESS_OP:
 514
 515                opcode = AML_INT_ACCESSFIELD_OP;
 516                parser_state->aml++;
 517                break;
 518
 519        case AML_FIELD_CONNECTION_OP:
 520
 521                opcode = AML_INT_CONNECTION_OP;
 522                parser_state->aml++;
 523                break;
 524
 525        case AML_FIELD_EXT_ACCESS_OP:
 526
 527                opcode = AML_INT_EXTACCESSFIELD_OP;
 528                parser_state->aml++;
 529                break;
 530
 531        default:
 532
 533                opcode = AML_INT_NAMEDFIELD_OP;
 534                break;
 535        }
 536
 537        /* Allocate a new field op */
 538
 539        field = acpi_ps_alloc_op(opcode);
 540        if (!field) {
 541                return_PTR(NULL);
 542        }
 543
 544        field->common.aml_offset = aml_offset;
 545
 546        /* Decode the field type */
 547
 548        switch (opcode) {
 549        case AML_INT_NAMEDFIELD_OP:
 550
 551                /* Get the 4-character name */
 552
 553                ACPI_MOVE_32_TO_32(&name, parser_state->aml);
 554                acpi_ps_set_name(field, name);
 555                parser_state->aml += ACPI_NAME_SIZE;
 556
 557                /* Get the length which is encoded as a package length */
 558
 559                field->common.value.size =
 560                    acpi_ps_get_next_package_length(parser_state);
 561                break;
 562
 563        case AML_INT_RESERVEDFIELD_OP:
 564
 565                /* Get the length which is encoded as a package length */
 566
 567                field->common.value.size =
 568                    acpi_ps_get_next_package_length(parser_state);
 569                break;
 570
 571        case AML_INT_ACCESSFIELD_OP:
 572        case AML_INT_EXTACCESSFIELD_OP:
 573
 574                /*
 575                 * Get access_type and access_attrib and merge into the field Op
 576                 * access_type is first operand, access_attribute is second. stuff
 577                 * these bytes into the node integer value for convenience.
 578                 */
 579
 580                /* Get the two bytes (Type/Attribute) */
 581
 582                access_type = ACPI_GET8(parser_state->aml);
 583                parser_state->aml++;
 584                access_attribute = ACPI_GET8(parser_state->aml);
 585                parser_state->aml++;
 586
 587                field->common.value.integer = (u8)access_type;
 588                field->common.value.integer |= (u16)(access_attribute << 8);
 589
 590                /* This opcode has a third byte, access_length */
 591
 592                if (opcode == AML_INT_EXTACCESSFIELD_OP) {
 593                        access_length = ACPI_GET8(parser_state->aml);
 594                        parser_state->aml++;
 595
 596                        field->common.value.integer |=
 597                            (u32)(access_length << 16);
 598                }
 599                break;
 600
 601        case AML_INT_CONNECTION_OP:
 602
 603                /*
 604                 * Argument for Connection operator can be either a Buffer
 605                 * (resource descriptor), or a name_string.
 606                 */
 607                if (ACPI_GET8(parser_state->aml) == AML_BUFFER_OP) {
 608                        parser_state->aml++;
 609
 610                        pkg_end = parser_state->aml;
 611                        pkg_length =
 612                            acpi_ps_get_next_package_length(parser_state);
 613                        pkg_end += pkg_length;
 614
 615                        if (parser_state->aml < pkg_end) {
 616
 617                                /* Non-empty list */
 618
 619                                arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP);
 620                                if (!arg) {
 621                                        acpi_ps_free_op(field);
 622                                        return_PTR(NULL);
 623                                }
 624
 625                                /* Get the actual buffer length argument */
 626
 627                                opcode = ACPI_GET8(parser_state->aml);
 628                                parser_state->aml++;
 629
 630                                switch (opcode) {
 631                                case AML_BYTE_OP:       /* AML_BYTEDATA_ARG */
 632                                        buffer_length =
 633                                            ACPI_GET8(parser_state->aml);
 634                                        parser_state->aml += 1;
 635                                        break;
 636
 637                                case AML_WORD_OP:       /* AML_WORDDATA_ARG */
 638                                        buffer_length =
 639                                            ACPI_GET16(parser_state->aml);
 640                                        parser_state->aml += 2;
 641                                        break;
 642
 643                                case AML_DWORD_OP:      /* AML_DWORDATA_ARG */
 644                                        buffer_length =
 645                                            ACPI_GET32(parser_state->aml);
 646                                        parser_state->aml += 4;
 647                                        break;
 648
 649                                default:
 650                                        buffer_length = 0;
 651                                        break;
 652                                }
 653
 654                                /* Fill in bytelist data */
 655
 656                                arg->named.value.size = buffer_length;
 657                                arg->named.data = parser_state->aml;
 658                        }
 659
 660                        /* Skip to End of byte data */
 661
 662                        parser_state->aml = pkg_end;
 663                } else {
 664                        arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
 665                        if (!arg) {
 666                                acpi_ps_free_op(field);
 667                                return_PTR(NULL);
 668                        }
 669
 670                        /* Get the Namestring argument */
 671
 672                        arg->common.value.name =
 673                            acpi_ps_get_next_namestring(parser_state);
 674                }
 675
 676                /* Link the buffer/namestring to parent (CONNECTION_OP) */
 677
 678                acpi_ps_append_arg(field, arg);
 679                break;
 680
 681        default:
 682
 683                /* Opcode was set in previous switch */
 684                break;
 685        }
 686
 687        return_PTR(field);
 688}
 689
 690/*******************************************************************************
 691 *
 692 * FUNCTION:    acpi_ps_get_next_arg
 693 *
 694 * PARAMETERS:  walk_state          - Current state
 695 *              parser_state        - Current parser state object
 696 *              arg_type            - The argument type (AML_*_ARG)
 697 *              return_arg          - Where the next arg is returned
 698 *
 699 * RETURN:      Status, and an op object containing the next argument.
 700 *
 701 * DESCRIPTION: Get next argument (including complex list arguments that require
 702 *              pushing the parser stack)
 703 *
 704 ******************************************************************************/
 705
 706acpi_status
 707acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
 708                     struct acpi_parse_state *parser_state,
 709                     u32 arg_type, union acpi_parse_object **return_arg)
 710{
 711        union acpi_parse_object *arg = NULL;
 712        union acpi_parse_object *prev = NULL;
 713        union acpi_parse_object *field;
 714        u32 subop;
 715        acpi_status status = AE_OK;
 716
 717        ACPI_FUNCTION_TRACE_PTR(ps_get_next_arg, parser_state);
 718
 719        switch (arg_type) {
 720        case ARGP_BYTEDATA:
 721        case ARGP_WORDDATA:
 722        case ARGP_DWORDDATA:
 723        case ARGP_CHARLIST:
 724        case ARGP_NAME:
 725        case ARGP_NAMESTRING:
 726
 727                /* Constants, strings, and namestrings are all the same size */
 728
 729                arg = acpi_ps_alloc_op(AML_BYTE_OP);
 730                if (!arg) {
 731                        return_ACPI_STATUS(AE_NO_MEMORY);
 732                }
 733                acpi_ps_get_next_simple_arg(parser_state, arg_type, arg);
 734                break;
 735
 736        case ARGP_PKGLENGTH:
 737
 738                /* Package length, nothing returned */
 739
 740                parser_state->pkg_end =
 741                    acpi_ps_get_next_package_end(parser_state);
 742                break;
 743
 744        case ARGP_FIELDLIST:
 745
 746                if (parser_state->aml < parser_state->pkg_end) {
 747
 748                        /* Non-empty list */
 749
 750                        while (parser_state->aml < parser_state->pkg_end) {
 751                                field = acpi_ps_get_next_field(parser_state);
 752                                if (!field) {
 753                                        return_ACPI_STATUS(AE_NO_MEMORY);
 754                                }
 755
 756                                if (prev) {
 757                                        prev->common.next = field;
 758                                } else {
 759                                        arg = field;
 760                                }
 761                                prev = field;
 762                        }
 763
 764                        /* Skip to End of byte data */
 765
 766                        parser_state->aml = parser_state->pkg_end;
 767                }
 768                break;
 769
 770        case ARGP_BYTELIST:
 771
 772                if (parser_state->aml < parser_state->pkg_end) {
 773
 774                        /* Non-empty list */
 775
 776                        arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP);
 777                        if (!arg) {
 778                                return_ACPI_STATUS(AE_NO_MEMORY);
 779                        }
 780
 781                        /* Fill in bytelist data */
 782
 783                        arg->common.value.size = (u32)
 784                            ACPI_PTR_DIFF(parser_state->pkg_end,
 785                                          parser_state->aml);
 786                        arg->named.data = parser_state->aml;
 787
 788                        /* Skip to End of byte data */
 789
 790                        parser_state->aml = parser_state->pkg_end;
 791                }
 792                break;
 793
 794        case ARGP_TARGET:
 795        case ARGP_SUPERNAME:
 796        case ARGP_SIMPLENAME:
 797
 798                subop = acpi_ps_peek_opcode(parser_state);
 799                if (subop == 0 ||
 800                    acpi_ps_is_leading_char(subop) ||
 801                    acpi_ps_is_prefix_char(subop)) {
 802
 803                        /* null_name or name_string */
 804
 805                        arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
 806                        if (!arg) {
 807                                return_ACPI_STATUS(AE_NO_MEMORY);
 808                        }
 809
 810                        /* To support super_name arg of Unload */
 811
 812                        if (walk_state->opcode == AML_UNLOAD_OP) {
 813                                status =
 814                                    acpi_ps_get_next_namepath(walk_state,
 815                                                              parser_state, arg,
 816                                                              1);
 817
 818                                /*
 819                                 * If the super_name arg of Unload is a method call,
 820                                 * we have restored the AML pointer, just free this Arg
 821                                 */
 822                                if (arg->common.aml_opcode ==
 823                                    AML_INT_METHODCALL_OP) {
 824                                        acpi_ps_free_op(arg);
 825                                        arg = NULL;
 826                                }
 827                        } else {
 828                                status =
 829                                    acpi_ps_get_next_namepath(walk_state,
 830                                                              parser_state, arg,
 831                                                              0);
 832                        }
 833                } else {
 834                        /* Single complex argument, nothing returned */
 835
 836                        walk_state->arg_count = 1;
 837                }
 838                break;
 839
 840        case ARGP_DATAOBJ:
 841        case ARGP_TERMARG:
 842
 843                /* Single complex argument, nothing returned */
 844
 845                walk_state->arg_count = 1;
 846                break;
 847
 848        case ARGP_DATAOBJLIST:
 849        case ARGP_TERMLIST:
 850        case ARGP_OBJLIST:
 851
 852                if (parser_state->aml < parser_state->pkg_end) {
 853
 854                        /* Non-empty list of variable arguments, nothing returned */
 855
 856                        walk_state->arg_count = ACPI_VAR_ARGS;
 857                }
 858                break;
 859
 860        default:
 861
 862                ACPI_ERROR((AE_INFO, "Invalid ArgType: 0x%X", arg_type));
 863                status = AE_AML_OPERAND_TYPE;
 864                break;
 865        }
 866
 867        *return_arg = arg;
 868        return_ACPI_STATUS(status);
 869}
 870