162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: psargs - Parse AML opcode arguments 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci *****************************************************************************/ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <acpi/acpi.h> 1162306a36Sopenharmony_ci#include "accommon.h" 1262306a36Sopenharmony_ci#include "acparser.h" 1362306a36Sopenharmony_ci#include "amlcode.h" 1462306a36Sopenharmony_ci#include "acnamesp.h" 1562306a36Sopenharmony_ci#include "acdispat.h" 1662306a36Sopenharmony_ci#include "acconvert.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define _COMPONENT ACPI_PARSER 1962306a36Sopenharmony_ciACPI_MODULE_NAME("psargs") 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* Local prototypes */ 2262306a36Sopenharmony_cistatic u32 2362306a36Sopenharmony_ciacpi_ps_get_next_package_length(struct acpi_parse_state *parser_state); 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state 2662306a36Sopenharmony_ci *parser_state); 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/******************************************************************************* 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * FUNCTION: acpi_ps_get_next_package_length 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci * PARAMETERS: parser_state - Current parser state object 3362306a36Sopenharmony_ci * 3462306a36Sopenharmony_ci * RETURN: Decoded package length. On completion, the AML pointer points 3562306a36Sopenharmony_ci * past the length byte or bytes. 3662306a36Sopenharmony_ci * 3762306a36Sopenharmony_ci * DESCRIPTION: Decode and return a package length field. 3862306a36Sopenharmony_ci * Note: Largest package length is 28 bits, from ACPI specification 3962306a36Sopenharmony_ci * 4062306a36Sopenharmony_ci ******************************************************************************/ 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic u32 4362306a36Sopenharmony_ciacpi_ps_get_next_package_length(struct acpi_parse_state *parser_state) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci u8 *aml = parser_state->aml; 4662306a36Sopenharmony_ci u32 package_length = 0; 4762306a36Sopenharmony_ci u32 byte_count; 4862306a36Sopenharmony_ci u8 byte_zero_mask = 0x3F; /* Default [0:5] */ 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ps_get_next_package_length); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci /* 5362306a36Sopenharmony_ci * Byte 0 bits [6:7] contain the number of additional bytes 5462306a36Sopenharmony_ci * used to encode the package length, either 0,1,2, or 3 5562306a36Sopenharmony_ci */ 5662306a36Sopenharmony_ci byte_count = (aml[0] >> 6); 5762306a36Sopenharmony_ci parser_state->aml += ((acpi_size)byte_count + 1); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci /* Get bytes 3, 2, 1 as needed */ 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci while (byte_count) { 6262306a36Sopenharmony_ci /* 6362306a36Sopenharmony_ci * Final bit positions for the package length bytes: 6462306a36Sopenharmony_ci * Byte3->[20:27] 6562306a36Sopenharmony_ci * Byte2->[12:19] 6662306a36Sopenharmony_ci * Byte1->[04:11] 6762306a36Sopenharmony_ci * Byte0->[00:03] 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_ci package_length |= (aml[byte_count] << ((byte_count << 3) - 4)); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci byte_zero_mask = 0x0F; /* Use bits [0:3] of byte 0 */ 7262306a36Sopenharmony_ci byte_count--; 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci /* Byte 0 is a special case, either bits [0:3] or [0:5] are used */ 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci package_length |= (aml[0] & byte_zero_mask); 7862306a36Sopenharmony_ci return_UINT32(package_length); 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/******************************************************************************* 8262306a36Sopenharmony_ci * 8362306a36Sopenharmony_ci * FUNCTION: acpi_ps_get_next_package_end 8462306a36Sopenharmony_ci * 8562306a36Sopenharmony_ci * PARAMETERS: parser_state - Current parser state object 8662306a36Sopenharmony_ci * 8762306a36Sopenharmony_ci * RETURN: Pointer to end-of-package +1 8862306a36Sopenharmony_ci * 8962306a36Sopenharmony_ci * DESCRIPTION: Get next package length and return a pointer past the end of 9062306a36Sopenharmony_ci * the package. Consumes the package length field 9162306a36Sopenharmony_ci * 9262306a36Sopenharmony_ci ******************************************************************************/ 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ciu8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci u8 *start = parser_state->aml; 9762306a36Sopenharmony_ci u32 package_length; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ps_get_next_package_end); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci /* Function below updates parser_state->Aml */ 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci package_length = acpi_ps_get_next_package_length(parser_state); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci return_PTR(start + package_length); /* end of package */ 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci/******************************************************************************* 10962306a36Sopenharmony_ci * 11062306a36Sopenharmony_ci * FUNCTION: acpi_ps_get_next_namestring 11162306a36Sopenharmony_ci * 11262306a36Sopenharmony_ci * PARAMETERS: parser_state - Current parser state object 11362306a36Sopenharmony_ci * 11462306a36Sopenharmony_ci * RETURN: Pointer to the start of the name string (pointer points into 11562306a36Sopenharmony_ci * the AML. 11662306a36Sopenharmony_ci * 11762306a36Sopenharmony_ci * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name 11862306a36Sopenharmony_ci * prefix characters. Set parser state to point past the string. 11962306a36Sopenharmony_ci * (Name is consumed from the AML.) 12062306a36Sopenharmony_ci * 12162306a36Sopenharmony_ci ******************************************************************************/ 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cichar *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci u8 *start = parser_state->aml; 12662306a36Sopenharmony_ci u8 *end = parser_state->aml; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ps_get_next_namestring); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci /* Point past any namestring prefix characters (backslash or carat) */ 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci while (ACPI_IS_ROOT_PREFIX(*end) || ACPI_IS_PARENT_PREFIX(*end)) { 13362306a36Sopenharmony_ci end++; 13462306a36Sopenharmony_ci } 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci /* Decode the path prefix character */ 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci switch (*end) { 13962306a36Sopenharmony_ci case 0: 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci /* null_name */ 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci if (end == start) { 14462306a36Sopenharmony_ci start = NULL; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci end++; 14762306a36Sopenharmony_ci break; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci case AML_DUAL_NAME_PREFIX: 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* Two name segments */ 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci end += 1 + (2 * ACPI_NAMESEG_SIZE); 15462306a36Sopenharmony_ci break; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci case AML_MULTI_NAME_PREFIX: 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci /* Multiple name segments, 4 chars each, count in next byte */ 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci end += 2 + (*(end + 1) * ACPI_NAMESEG_SIZE); 16162306a36Sopenharmony_ci break; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci default: 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci /* Single name segment */ 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci end += ACPI_NAMESEG_SIZE; 16862306a36Sopenharmony_ci break; 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci parser_state->aml = end; 17262306a36Sopenharmony_ci return_PTR((char *)start); 17362306a36Sopenharmony_ci} 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci/******************************************************************************* 17662306a36Sopenharmony_ci * 17762306a36Sopenharmony_ci * FUNCTION: acpi_ps_get_next_namepath 17862306a36Sopenharmony_ci * 17962306a36Sopenharmony_ci * PARAMETERS: parser_state - Current parser state object 18062306a36Sopenharmony_ci * arg - Where the namepath will be stored 18162306a36Sopenharmony_ci * arg_count - If the namepath points to a control method 18262306a36Sopenharmony_ci * the method's argument is returned here. 18362306a36Sopenharmony_ci * possible_method_call - Whether the namepath can possibly be the 18462306a36Sopenharmony_ci * start of a method call 18562306a36Sopenharmony_ci * 18662306a36Sopenharmony_ci * RETURN: Status 18762306a36Sopenharmony_ci * 18862306a36Sopenharmony_ci * DESCRIPTION: Get next name (if method call, return # of required args). 18962306a36Sopenharmony_ci * Names are looked up in the internal namespace to determine 19062306a36Sopenharmony_ci * if the name represents a control method. If a method 19162306a36Sopenharmony_ci * is found, the number of arguments to the method is returned. 19262306a36Sopenharmony_ci * This information is critical for parsing to continue correctly. 19362306a36Sopenharmony_ci * 19462306a36Sopenharmony_ci ******************************************************************************/ 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ciacpi_status 19762306a36Sopenharmony_ciacpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, 19862306a36Sopenharmony_ci struct acpi_parse_state *parser_state, 19962306a36Sopenharmony_ci union acpi_parse_object *arg, u8 possible_method_call) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci acpi_status status; 20262306a36Sopenharmony_ci char *path; 20362306a36Sopenharmony_ci union acpi_parse_object *name_op; 20462306a36Sopenharmony_ci union acpi_operand_object *method_desc; 20562306a36Sopenharmony_ci struct acpi_namespace_node *node; 20662306a36Sopenharmony_ci u8 *start = parser_state->aml; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ps_get_next_namepath); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci path = acpi_ps_get_next_namestring(parser_state); 21162306a36Sopenharmony_ci acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci /* Null path case is allowed, just exit */ 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci if (!path) { 21662306a36Sopenharmony_ci arg->common.value.name = path; 21762306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci /* 22162306a36Sopenharmony_ci * Lookup the name in the internal namespace, starting with the current 22262306a36Sopenharmony_ci * scope. We don't want to add anything new to the namespace here, 22362306a36Sopenharmony_ci * however, so we use MODE_EXECUTE. 22462306a36Sopenharmony_ci * Allow searching of the parent tree, but don't open a new scope - 22562306a36Sopenharmony_ci * we just want to lookup the object (must be mode EXECUTE to perform 22662306a36Sopenharmony_ci * the upsearch) 22762306a36Sopenharmony_ci */ 22862306a36Sopenharmony_ci status = acpi_ns_lookup(walk_state->scope_info, path, 22962306a36Sopenharmony_ci ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 23062306a36Sopenharmony_ci ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 23162306a36Sopenharmony_ci NULL, &node); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci /* 23462306a36Sopenharmony_ci * If this name is a control method invocation, we must 23562306a36Sopenharmony_ci * setup the method call 23662306a36Sopenharmony_ci */ 23762306a36Sopenharmony_ci if (ACPI_SUCCESS(status) && 23862306a36Sopenharmony_ci possible_method_call && (node->type == ACPI_TYPE_METHOD)) { 23962306a36Sopenharmony_ci if ((GET_CURRENT_ARG_TYPE(walk_state->arg_types) == 24062306a36Sopenharmony_ci ARGP_SUPERNAME) 24162306a36Sopenharmony_ci || (GET_CURRENT_ARG_TYPE(walk_state->arg_types) == 24262306a36Sopenharmony_ci ARGP_TARGET)) { 24362306a36Sopenharmony_ci /* 24462306a36Sopenharmony_ci * acpi_ps_get_next_namestring has increased the AML pointer past 24562306a36Sopenharmony_ci * the method invocation namestring, so we need to restore the 24662306a36Sopenharmony_ci * saved AML pointer back to the original method invocation 24762306a36Sopenharmony_ci * namestring. 24862306a36Sopenharmony_ci */ 24962306a36Sopenharmony_ci walk_state->parser_state.aml = start; 25062306a36Sopenharmony_ci walk_state->arg_count = 1; 25162306a36Sopenharmony_ci acpi_ps_init_op(arg, AML_INT_METHODCALL_OP); 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* This name is actually a control method invocation */ 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci method_desc = acpi_ns_get_attached_object(node); 25762306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 25862306a36Sopenharmony_ci "Control Method invocation %4.4s - %p Desc %p Path=%p\n", 25962306a36Sopenharmony_ci node->name.ascii, node, method_desc, path)); 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP, start); 26262306a36Sopenharmony_ci if (!name_op) { 26362306a36Sopenharmony_ci return_ACPI_STATUS(AE_NO_MEMORY); 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci /* Change Arg into a METHOD CALL and attach name to it */ 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci acpi_ps_init_op(arg, AML_INT_METHODCALL_OP); 26962306a36Sopenharmony_ci name_op->common.value.name = path; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci /* Point METHODCALL/NAME to the METHOD Node */ 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci name_op->common.node = node; 27462306a36Sopenharmony_ci acpi_ps_append_arg(arg, name_op); 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci if (!method_desc) { 27762306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 27862306a36Sopenharmony_ci "Control Method %p has no attached object", 27962306a36Sopenharmony_ci node)); 28062306a36Sopenharmony_ci return_ACPI_STATUS(AE_AML_INTERNAL); 28162306a36Sopenharmony_ci } 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 28462306a36Sopenharmony_ci "Control Method - %p Args %X\n", 28562306a36Sopenharmony_ci node, method_desc->method.param_count)); 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci /* Get the number of arguments to expect */ 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci walk_state->arg_count = method_desc->method.param_count; 29062306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 29162306a36Sopenharmony_ci } 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci /* 29462306a36Sopenharmony_ci * Special handling if the name was not found during the lookup - 29562306a36Sopenharmony_ci * some not_found cases are allowed 29662306a36Sopenharmony_ci */ 29762306a36Sopenharmony_ci if (status == AE_NOT_FOUND) { 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci /* 1) not_found is ok during load pass 1/2 (allow forward references) */ 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) != 30262306a36Sopenharmony_ci ACPI_PARSE_EXECUTE) { 30362306a36Sopenharmony_ci status = AE_OK; 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci /* 2) not_found during a cond_ref_of(x) is ok by definition */ 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci else if (walk_state->op->common.aml_opcode == 30962306a36Sopenharmony_ci AML_CONDITIONAL_REF_OF_OP) { 31062306a36Sopenharmony_ci status = AE_OK; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci /* 31462306a36Sopenharmony_ci * 3) not_found while building a Package is ok at this point, we 31562306a36Sopenharmony_ci * may flag as an error later if slack mode is not enabled. 31662306a36Sopenharmony_ci * (Some ASL code depends on allowing this behavior) 31762306a36Sopenharmony_ci */ 31862306a36Sopenharmony_ci else if ((arg->common.parent) && 31962306a36Sopenharmony_ci ((arg->common.parent->common.aml_opcode == 32062306a36Sopenharmony_ci AML_PACKAGE_OP) 32162306a36Sopenharmony_ci || (arg->common.parent->common.aml_opcode == 32262306a36Sopenharmony_ci AML_VARIABLE_PACKAGE_OP))) { 32362306a36Sopenharmony_ci status = AE_OK; 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci /* Final exception check (may have been changed from code above) */ 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 33062306a36Sopenharmony_ci ACPI_ERROR_NAMESPACE(walk_state->scope_info, path, status); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == 33362306a36Sopenharmony_ci ACPI_PARSE_EXECUTE) { 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci /* Report a control method execution error */ 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci status = acpi_ds_method_error(status, walk_state); 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci /* Save the namepath */ 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci arg->common.value.name = path; 34462306a36Sopenharmony_ci return_ACPI_STATUS(status); 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci/******************************************************************************* 34862306a36Sopenharmony_ci * 34962306a36Sopenharmony_ci * FUNCTION: acpi_ps_get_next_simple_arg 35062306a36Sopenharmony_ci * 35162306a36Sopenharmony_ci * PARAMETERS: parser_state - Current parser state object 35262306a36Sopenharmony_ci * arg_type - The argument type (AML_*_ARG) 35362306a36Sopenharmony_ci * arg - Where the argument is returned 35462306a36Sopenharmony_ci * 35562306a36Sopenharmony_ci * RETURN: None 35662306a36Sopenharmony_ci * 35762306a36Sopenharmony_ci * DESCRIPTION: Get the next simple argument (constant, string, or namestring) 35862306a36Sopenharmony_ci * 35962306a36Sopenharmony_ci ******************************************************************************/ 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_civoid 36262306a36Sopenharmony_ciacpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, 36362306a36Sopenharmony_ci u32 arg_type, union acpi_parse_object *arg) 36462306a36Sopenharmony_ci{ 36562306a36Sopenharmony_ci u32 length; 36662306a36Sopenharmony_ci u16 opcode; 36762306a36Sopenharmony_ci u8 *aml = parser_state->aml; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci ACPI_FUNCTION_TRACE_U32(ps_get_next_simple_arg, arg_type); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci switch (arg_type) { 37262306a36Sopenharmony_ci case ARGP_BYTEDATA: 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci /* Get 1 byte from the AML stream */ 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci opcode = AML_BYTE_OP; 37762306a36Sopenharmony_ci arg->common.value.integer = (u64) *aml; 37862306a36Sopenharmony_ci length = 1; 37962306a36Sopenharmony_ci break; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci case ARGP_WORDDATA: 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci /* Get 2 bytes from the AML stream */ 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci opcode = AML_WORD_OP; 38662306a36Sopenharmony_ci ACPI_MOVE_16_TO_64(&arg->common.value.integer, aml); 38762306a36Sopenharmony_ci length = 2; 38862306a36Sopenharmony_ci break; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci case ARGP_DWORDDATA: 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci /* Get 4 bytes from the AML stream */ 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci opcode = AML_DWORD_OP; 39562306a36Sopenharmony_ci ACPI_MOVE_32_TO_64(&arg->common.value.integer, aml); 39662306a36Sopenharmony_ci length = 4; 39762306a36Sopenharmony_ci break; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci case ARGP_QWORDDATA: 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci /* Get 8 bytes from the AML stream */ 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci opcode = AML_QWORD_OP; 40462306a36Sopenharmony_ci ACPI_MOVE_64_TO_64(&arg->common.value.integer, aml); 40562306a36Sopenharmony_ci length = 8; 40662306a36Sopenharmony_ci break; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci case ARGP_CHARLIST: 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci /* Get a pointer to the string, point past the string */ 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci opcode = AML_STRING_OP; 41362306a36Sopenharmony_ci arg->common.value.string = ACPI_CAST_PTR(char, aml); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci /* Find the null terminator */ 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci length = 0; 41862306a36Sopenharmony_ci while (aml[length]) { 41962306a36Sopenharmony_ci length++; 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci length++; 42262306a36Sopenharmony_ci break; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci case ARGP_NAME: 42562306a36Sopenharmony_ci case ARGP_NAMESTRING: 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP); 42862306a36Sopenharmony_ci arg->common.value.name = 42962306a36Sopenharmony_ci acpi_ps_get_next_namestring(parser_state); 43062306a36Sopenharmony_ci return_VOID; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci default: 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, "Invalid ArgType 0x%X", arg_type)); 43562306a36Sopenharmony_ci return_VOID; 43662306a36Sopenharmony_ci } 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci acpi_ps_init_op(arg, opcode); 43962306a36Sopenharmony_ci parser_state->aml += length; 44062306a36Sopenharmony_ci return_VOID; 44162306a36Sopenharmony_ci} 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci/******************************************************************************* 44462306a36Sopenharmony_ci * 44562306a36Sopenharmony_ci * FUNCTION: acpi_ps_get_next_field 44662306a36Sopenharmony_ci * 44762306a36Sopenharmony_ci * PARAMETERS: parser_state - Current parser state object 44862306a36Sopenharmony_ci * 44962306a36Sopenharmony_ci * RETURN: A newly allocated FIELD op 45062306a36Sopenharmony_ci * 45162306a36Sopenharmony_ci * DESCRIPTION: Get next field (named_field, reserved_field, or access_field) 45262306a36Sopenharmony_ci * 45362306a36Sopenharmony_ci ******************************************************************************/ 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_cistatic union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state 45662306a36Sopenharmony_ci *parser_state) 45762306a36Sopenharmony_ci{ 45862306a36Sopenharmony_ci u8 *aml; 45962306a36Sopenharmony_ci union acpi_parse_object *field; 46062306a36Sopenharmony_ci union acpi_parse_object *arg = NULL; 46162306a36Sopenharmony_ci u16 opcode; 46262306a36Sopenharmony_ci u32 name; 46362306a36Sopenharmony_ci u8 access_type; 46462306a36Sopenharmony_ci u8 access_attribute; 46562306a36Sopenharmony_ci u8 access_length; 46662306a36Sopenharmony_ci u32 pkg_length; 46762306a36Sopenharmony_ci u8 *pkg_end; 46862306a36Sopenharmony_ci u32 buffer_length; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ps_get_next_field); 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci ASL_CV_CAPTURE_COMMENTS_ONLY(parser_state); 47362306a36Sopenharmony_ci aml = parser_state->aml; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci /* Determine field type */ 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci switch (ACPI_GET8(parser_state->aml)) { 47862306a36Sopenharmony_ci case AML_FIELD_OFFSET_OP: 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci opcode = AML_INT_RESERVEDFIELD_OP; 48162306a36Sopenharmony_ci parser_state->aml++; 48262306a36Sopenharmony_ci break; 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci case AML_FIELD_ACCESS_OP: 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci opcode = AML_INT_ACCESSFIELD_OP; 48762306a36Sopenharmony_ci parser_state->aml++; 48862306a36Sopenharmony_ci break; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci case AML_FIELD_CONNECTION_OP: 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci opcode = AML_INT_CONNECTION_OP; 49362306a36Sopenharmony_ci parser_state->aml++; 49462306a36Sopenharmony_ci break; 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci case AML_FIELD_EXT_ACCESS_OP: 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci opcode = AML_INT_EXTACCESSFIELD_OP; 49962306a36Sopenharmony_ci parser_state->aml++; 50062306a36Sopenharmony_ci break; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci default: 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci opcode = AML_INT_NAMEDFIELD_OP; 50562306a36Sopenharmony_ci break; 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci /* Allocate a new field op */ 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci field = acpi_ps_alloc_op(opcode, aml); 51162306a36Sopenharmony_ci if (!field) { 51262306a36Sopenharmony_ci return_PTR(NULL); 51362306a36Sopenharmony_ci } 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci /* Decode the field type */ 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci ASL_CV_CAPTURE_COMMENTS_ONLY(parser_state); 51862306a36Sopenharmony_ci switch (opcode) { 51962306a36Sopenharmony_ci case AML_INT_NAMEDFIELD_OP: 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci /* Get the 4-character name */ 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci ACPI_MOVE_32_TO_32(&name, parser_state->aml); 52462306a36Sopenharmony_ci acpi_ps_set_name(field, name); 52562306a36Sopenharmony_ci parser_state->aml += ACPI_NAMESEG_SIZE; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci ASL_CV_CAPTURE_COMMENTS_ONLY(parser_state); 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci#ifdef ACPI_ASL_COMPILER 53062306a36Sopenharmony_ci /* 53162306a36Sopenharmony_ci * Because the package length isn't represented as a parse tree object, 53262306a36Sopenharmony_ci * take comments surrounding this and add to the previously created 53362306a36Sopenharmony_ci * parse node. 53462306a36Sopenharmony_ci */ 53562306a36Sopenharmony_ci if (field->common.inline_comment) { 53662306a36Sopenharmony_ci field->common.name_comment = 53762306a36Sopenharmony_ci field->common.inline_comment; 53862306a36Sopenharmony_ci } 53962306a36Sopenharmony_ci field->common.inline_comment = acpi_gbl_current_inline_comment; 54062306a36Sopenharmony_ci acpi_gbl_current_inline_comment = NULL; 54162306a36Sopenharmony_ci#endif 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci /* Get the length which is encoded as a package length */ 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci field->common.value.size = 54662306a36Sopenharmony_ci acpi_ps_get_next_package_length(parser_state); 54762306a36Sopenharmony_ci break; 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci case AML_INT_RESERVEDFIELD_OP: 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci /* Get the length which is encoded as a package length */ 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci field->common.value.size = 55462306a36Sopenharmony_ci acpi_ps_get_next_package_length(parser_state); 55562306a36Sopenharmony_ci break; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci case AML_INT_ACCESSFIELD_OP: 55862306a36Sopenharmony_ci case AML_INT_EXTACCESSFIELD_OP: 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci /* 56162306a36Sopenharmony_ci * Get access_type and access_attrib and merge into the field Op 56262306a36Sopenharmony_ci * access_type is first operand, access_attribute is second. stuff 56362306a36Sopenharmony_ci * these bytes into the node integer value for convenience. 56462306a36Sopenharmony_ci */ 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci /* Get the two bytes (Type/Attribute) */ 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci access_type = ACPI_GET8(parser_state->aml); 56962306a36Sopenharmony_ci parser_state->aml++; 57062306a36Sopenharmony_ci access_attribute = ACPI_GET8(parser_state->aml); 57162306a36Sopenharmony_ci parser_state->aml++; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci field->common.value.integer = (u8)access_type; 57462306a36Sopenharmony_ci field->common.value.integer |= (u16)(access_attribute << 8); 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci /* This opcode has a third byte, access_length */ 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci if (opcode == AML_INT_EXTACCESSFIELD_OP) { 57962306a36Sopenharmony_ci access_length = ACPI_GET8(parser_state->aml); 58062306a36Sopenharmony_ci parser_state->aml++; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci field->common.value.integer |= 58362306a36Sopenharmony_ci (u32)(access_length << 16); 58462306a36Sopenharmony_ci } 58562306a36Sopenharmony_ci break; 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci case AML_INT_CONNECTION_OP: 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci /* 59062306a36Sopenharmony_ci * Argument for Connection operator can be either a Buffer 59162306a36Sopenharmony_ci * (resource descriptor), or a name_string. 59262306a36Sopenharmony_ci */ 59362306a36Sopenharmony_ci aml = parser_state->aml; 59462306a36Sopenharmony_ci if (ACPI_GET8(parser_state->aml) == AML_BUFFER_OP) { 59562306a36Sopenharmony_ci parser_state->aml++; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci ASL_CV_CAPTURE_COMMENTS_ONLY(parser_state); 59862306a36Sopenharmony_ci pkg_end = parser_state->aml; 59962306a36Sopenharmony_ci pkg_length = 60062306a36Sopenharmony_ci acpi_ps_get_next_package_length(parser_state); 60162306a36Sopenharmony_ci pkg_end += pkg_length; 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci ASL_CV_CAPTURE_COMMENTS_ONLY(parser_state); 60462306a36Sopenharmony_ci if (parser_state->aml < pkg_end) { 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci /* Non-empty list */ 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci arg = 60962306a36Sopenharmony_ci acpi_ps_alloc_op(AML_INT_BYTELIST_OP, aml); 61062306a36Sopenharmony_ci if (!arg) { 61162306a36Sopenharmony_ci acpi_ps_free_op(field); 61262306a36Sopenharmony_ci return_PTR(NULL); 61362306a36Sopenharmony_ci } 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci /* Get the actual buffer length argument */ 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci opcode = ACPI_GET8(parser_state->aml); 61862306a36Sopenharmony_ci parser_state->aml++; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci ASL_CV_CAPTURE_COMMENTS_ONLY(parser_state); 62162306a36Sopenharmony_ci switch (opcode) { 62262306a36Sopenharmony_ci case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci buffer_length = 62562306a36Sopenharmony_ci ACPI_GET8(parser_state->aml); 62662306a36Sopenharmony_ci parser_state->aml += 1; 62762306a36Sopenharmony_ci break; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci case AML_WORD_OP: /* AML_WORDDATA_ARG */ 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci buffer_length = 63262306a36Sopenharmony_ci ACPI_GET16(parser_state->aml); 63362306a36Sopenharmony_ci parser_state->aml += 2; 63462306a36Sopenharmony_ci break; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci case AML_DWORD_OP: /* AML_DWORDATA_ARG */ 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci buffer_length = 63962306a36Sopenharmony_ci ACPI_GET32(parser_state->aml); 64062306a36Sopenharmony_ci parser_state->aml += 4; 64162306a36Sopenharmony_ci break; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci default: 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci buffer_length = 0; 64662306a36Sopenharmony_ci break; 64762306a36Sopenharmony_ci } 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci /* Fill in bytelist data */ 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci ASL_CV_CAPTURE_COMMENTS_ONLY(parser_state); 65262306a36Sopenharmony_ci arg->named.value.size = buffer_length; 65362306a36Sopenharmony_ci arg->named.data = parser_state->aml; 65462306a36Sopenharmony_ci } 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci /* Skip to End of byte data */ 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci parser_state->aml = pkg_end; 65962306a36Sopenharmony_ci } else { 66062306a36Sopenharmony_ci arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP, aml); 66162306a36Sopenharmony_ci if (!arg) { 66262306a36Sopenharmony_ci acpi_ps_free_op(field); 66362306a36Sopenharmony_ci return_PTR(NULL); 66462306a36Sopenharmony_ci } 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci /* Get the Namestring argument */ 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci arg->common.value.name = 66962306a36Sopenharmony_ci acpi_ps_get_next_namestring(parser_state); 67062306a36Sopenharmony_ci } 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci /* Link the buffer/namestring to parent (CONNECTION_OP) */ 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci acpi_ps_append_arg(field, arg); 67562306a36Sopenharmony_ci break; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci default: 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci /* Opcode was set in previous switch */ 68062306a36Sopenharmony_ci break; 68162306a36Sopenharmony_ci } 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci return_PTR(field); 68462306a36Sopenharmony_ci} 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci/******************************************************************************* 68762306a36Sopenharmony_ci * 68862306a36Sopenharmony_ci * FUNCTION: acpi_ps_get_next_arg 68962306a36Sopenharmony_ci * 69062306a36Sopenharmony_ci * PARAMETERS: walk_state - Current state 69162306a36Sopenharmony_ci * parser_state - Current parser state object 69262306a36Sopenharmony_ci * arg_type - The argument type (AML_*_ARG) 69362306a36Sopenharmony_ci * return_arg - Where the next arg is returned 69462306a36Sopenharmony_ci * 69562306a36Sopenharmony_ci * RETURN: Status, and an op object containing the next argument. 69662306a36Sopenharmony_ci * 69762306a36Sopenharmony_ci * DESCRIPTION: Get next argument (including complex list arguments that require 69862306a36Sopenharmony_ci * pushing the parser stack) 69962306a36Sopenharmony_ci * 70062306a36Sopenharmony_ci ******************************************************************************/ 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ciacpi_status 70362306a36Sopenharmony_ciacpi_ps_get_next_arg(struct acpi_walk_state *walk_state, 70462306a36Sopenharmony_ci struct acpi_parse_state *parser_state, 70562306a36Sopenharmony_ci u32 arg_type, union acpi_parse_object **return_arg) 70662306a36Sopenharmony_ci{ 70762306a36Sopenharmony_ci union acpi_parse_object *arg = NULL; 70862306a36Sopenharmony_ci union acpi_parse_object *prev = NULL; 70962306a36Sopenharmony_ci union acpi_parse_object *field; 71062306a36Sopenharmony_ci u32 subop; 71162306a36Sopenharmony_ci acpi_status status = AE_OK; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci ACPI_FUNCTION_TRACE_PTR(ps_get_next_arg, parser_state); 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 71662306a36Sopenharmony_ci "Expected argument type ARGP: %s (%2.2X)\n", 71762306a36Sopenharmony_ci acpi_ut_get_argument_type_name(arg_type), arg_type)); 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci switch (arg_type) { 72062306a36Sopenharmony_ci case ARGP_BYTEDATA: 72162306a36Sopenharmony_ci case ARGP_WORDDATA: 72262306a36Sopenharmony_ci case ARGP_DWORDDATA: 72362306a36Sopenharmony_ci case ARGP_CHARLIST: 72462306a36Sopenharmony_ci case ARGP_NAME: 72562306a36Sopenharmony_ci case ARGP_NAMESTRING: 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci /* Constants, strings, and namestrings are all the same size */ 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci arg = acpi_ps_alloc_op(AML_BYTE_OP, parser_state->aml); 73062306a36Sopenharmony_ci if (!arg) { 73162306a36Sopenharmony_ci return_ACPI_STATUS(AE_NO_MEMORY); 73262306a36Sopenharmony_ci } 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci acpi_ps_get_next_simple_arg(parser_state, arg_type, arg); 73562306a36Sopenharmony_ci break; 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci case ARGP_PKGLENGTH: 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci /* Package length, nothing returned */ 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci parser_state->pkg_end = 74262306a36Sopenharmony_ci acpi_ps_get_next_package_end(parser_state); 74362306a36Sopenharmony_ci break; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci case ARGP_FIELDLIST: 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci if (parser_state->aml < parser_state->pkg_end) { 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci /* Non-empty list */ 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci while (parser_state->aml < parser_state->pkg_end) { 75262306a36Sopenharmony_ci field = acpi_ps_get_next_field(parser_state); 75362306a36Sopenharmony_ci if (!field) { 75462306a36Sopenharmony_ci return_ACPI_STATUS(AE_NO_MEMORY); 75562306a36Sopenharmony_ci } 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci if (prev) { 75862306a36Sopenharmony_ci prev->common.next = field; 75962306a36Sopenharmony_ci } else { 76062306a36Sopenharmony_ci arg = field; 76162306a36Sopenharmony_ci } 76262306a36Sopenharmony_ci prev = field; 76362306a36Sopenharmony_ci } 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci /* Skip to End of byte data */ 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci parser_state->aml = parser_state->pkg_end; 76862306a36Sopenharmony_ci } 76962306a36Sopenharmony_ci break; 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci case ARGP_BYTELIST: 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci if (parser_state->aml < parser_state->pkg_end) { 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci /* Non-empty list */ 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP, 77862306a36Sopenharmony_ci parser_state->aml); 77962306a36Sopenharmony_ci if (!arg) { 78062306a36Sopenharmony_ci return_ACPI_STATUS(AE_NO_MEMORY); 78162306a36Sopenharmony_ci } 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci /* Fill in bytelist data */ 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci arg->common.value.size = (u32) 78662306a36Sopenharmony_ci ACPI_PTR_DIFF(parser_state->pkg_end, 78762306a36Sopenharmony_ci parser_state->aml); 78862306a36Sopenharmony_ci arg->named.data = parser_state->aml; 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci /* Skip to End of byte data */ 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci parser_state->aml = parser_state->pkg_end; 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci break; 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci case ARGP_SIMPLENAME: 79762306a36Sopenharmony_ci case ARGP_NAME_OR_REF: 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 80062306a36Sopenharmony_ci "**** SimpleName/NameOrRef: %s (%2.2X)\n", 80162306a36Sopenharmony_ci acpi_ut_get_argument_type_name(arg_type), 80262306a36Sopenharmony_ci arg_type)); 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci subop = acpi_ps_peek_opcode(parser_state); 80562306a36Sopenharmony_ci if (subop == 0 || 80662306a36Sopenharmony_ci acpi_ps_is_leading_char(subop) || 80762306a36Sopenharmony_ci ACPI_IS_ROOT_PREFIX(subop) || 80862306a36Sopenharmony_ci ACPI_IS_PARENT_PREFIX(subop)) { 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci /* null_name or name_string */ 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci arg = 81362306a36Sopenharmony_ci acpi_ps_alloc_op(AML_INT_NAMEPATH_OP, 81462306a36Sopenharmony_ci parser_state->aml); 81562306a36Sopenharmony_ci if (!arg) { 81662306a36Sopenharmony_ci return_ACPI_STATUS(AE_NO_MEMORY); 81762306a36Sopenharmony_ci } 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci status = 82062306a36Sopenharmony_ci acpi_ps_get_next_namepath(walk_state, parser_state, 82162306a36Sopenharmony_ci arg, 82262306a36Sopenharmony_ci ACPI_NOT_METHOD_CALL); 82362306a36Sopenharmony_ci } else { 82462306a36Sopenharmony_ci /* Single complex argument, nothing returned */ 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci walk_state->arg_count = 1; 82762306a36Sopenharmony_ci } 82862306a36Sopenharmony_ci break; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci case ARGP_TARGET: 83162306a36Sopenharmony_ci case ARGP_SUPERNAME: 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 83462306a36Sopenharmony_ci "**** Target/Supername: %s (%2.2X)\n", 83562306a36Sopenharmony_ci acpi_ut_get_argument_type_name(arg_type), 83662306a36Sopenharmony_ci arg_type)); 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci subop = acpi_ps_peek_opcode(parser_state); 83962306a36Sopenharmony_ci if (subop == 0 || 84062306a36Sopenharmony_ci acpi_ps_is_leading_char(subop) || 84162306a36Sopenharmony_ci ACPI_IS_ROOT_PREFIX(subop) || 84262306a36Sopenharmony_ci ACPI_IS_PARENT_PREFIX(subop)) { 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci /* NULL target (zero). Convert to a NULL namepath */ 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci arg = 84762306a36Sopenharmony_ci acpi_ps_alloc_op(AML_INT_NAMEPATH_OP, 84862306a36Sopenharmony_ci parser_state->aml); 84962306a36Sopenharmony_ci if (!arg) { 85062306a36Sopenharmony_ci return_ACPI_STATUS(AE_NO_MEMORY); 85162306a36Sopenharmony_ci } 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci status = 85462306a36Sopenharmony_ci acpi_ps_get_next_namepath(walk_state, parser_state, 85562306a36Sopenharmony_ci arg, 85662306a36Sopenharmony_ci ACPI_POSSIBLE_METHOD_CALL); 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci if (arg->common.aml_opcode == AML_INT_METHODCALL_OP) { 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci /* Free method call op and corresponding namestring sub-ob */ 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci acpi_ps_free_op(arg->common.value.arg); 86362306a36Sopenharmony_ci acpi_ps_free_op(arg); 86462306a36Sopenharmony_ci arg = NULL; 86562306a36Sopenharmony_ci walk_state->arg_count = 1; 86662306a36Sopenharmony_ci } 86762306a36Sopenharmony_ci } else { 86862306a36Sopenharmony_ci /* Single complex argument, nothing returned */ 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci walk_state->arg_count = 1; 87162306a36Sopenharmony_ci } 87262306a36Sopenharmony_ci break; 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci case ARGP_DATAOBJ: 87562306a36Sopenharmony_ci case ARGP_TERMARG: 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 87862306a36Sopenharmony_ci "**** TermArg/DataObj: %s (%2.2X)\n", 87962306a36Sopenharmony_ci acpi_ut_get_argument_type_name(arg_type), 88062306a36Sopenharmony_ci arg_type)); 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci /* Single complex argument, nothing returned */ 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci walk_state->arg_count = 1; 88562306a36Sopenharmony_ci break; 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci case ARGP_DATAOBJLIST: 88862306a36Sopenharmony_ci case ARGP_TERMLIST: 88962306a36Sopenharmony_ci case ARGP_OBJLIST: 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci if (parser_state->aml < parser_state->pkg_end) { 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci /* Non-empty list of variable arguments, nothing returned */ 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci walk_state->arg_count = ACPI_VAR_ARGS; 89662306a36Sopenharmony_ci } 89762306a36Sopenharmony_ci break; 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci default: 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, "Invalid ArgType: 0x%X", arg_type)); 90262306a36Sopenharmony_ci status = AE_AML_OPERAND_TYPE; 90362306a36Sopenharmony_ci break; 90462306a36Sopenharmony_ci } 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci *return_arg = arg; 90762306a36Sopenharmony_ci return_ACPI_STATUS(status); 90862306a36Sopenharmony_ci} 909