195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /******************************************************************************
395b482a8SLen Brown *
495b482a8SLen Brown * Module Name: dsfield - Dispatcher field routines
595b482a8SLen Brown *
6*612c2932SBob Moore * Copyright (C) 2000 - 2023, Intel Corp.
795b482a8SLen Brown *
895857638SErik Schmauss *****************************************************************************/
995b482a8SLen Brown
1095b482a8SLen Brown #include <acpi/acpi.h>
11e2f7a777SLen Brown #include "accommon.h"
12e2f7a777SLen Brown #include "amlcode.h"
13e2f7a777SLen Brown #include "acdispat.h"
14e2f7a777SLen Brown #include "acinterp.h"
15e2f7a777SLen Brown #include "acnamesp.h"
16e2f7a777SLen Brown #include "acparser.h"
1795b482a8SLen Brown
1877d4e096SErik Schmauss #ifdef ACPI_EXEC_APP
1977d4e096SErik Schmauss #include "aecommon.h"
2077d4e096SErik Schmauss #endif
2177d4e096SErik Schmauss
2295b482a8SLen Brown #define _COMPONENT ACPI_DISPATCHER
2395b482a8SLen Brown ACPI_MODULE_NAME("dsfield")
2495b482a8SLen Brown
2595b482a8SLen Brown /* Local prototypes */
266ccd7b5aSBob Moore #ifdef ACPI_ASL_COMPILER
276ccd7b5aSBob Moore #include "acdisasm.h"
286ccd7b5aSBob Moore static acpi_status
296ccd7b5aSBob Moore acpi_ds_create_external_region(acpi_status lookup_status,
306ccd7b5aSBob Moore union acpi_parse_object *op,
316ccd7b5aSBob Moore char *path,
326ccd7b5aSBob Moore struct acpi_walk_state *walk_state,
336ccd7b5aSBob Moore struct acpi_namespace_node **node);
346ccd7b5aSBob Moore #endif
356ccd7b5aSBob Moore
3695b482a8SLen Brown static acpi_status
3795b482a8SLen Brown acpi_ds_get_field_names(struct acpi_create_field_info *info,
3895b482a8SLen Brown struct acpi_walk_state *walk_state,
3995b482a8SLen Brown union acpi_parse_object *arg);
4095b482a8SLen Brown
416ccd7b5aSBob Moore #ifdef ACPI_ASL_COMPILER
426ccd7b5aSBob Moore /*******************************************************************************
436ccd7b5aSBob Moore *
44ba494beeSBob Moore * FUNCTION: acpi_ds_create_external_region (iASL Disassembler only)
456ccd7b5aSBob Moore *
466ccd7b5aSBob Moore * PARAMETERS: lookup_status - Status from ns_lookup operation
47ba494beeSBob Moore * op - Op containing the Field definition and args
48ba494beeSBob Moore * path - Pathname of the region
496ccd7b5aSBob Moore * ` walk_state - Current method state
50ba494beeSBob Moore * node - Where the new region node is returned
516ccd7b5aSBob Moore *
526ccd7b5aSBob Moore * RETURN: Status
536ccd7b5aSBob Moore *
546ccd7b5aSBob Moore * DESCRIPTION: Add region to the external list if NOT_FOUND. Create a new
556ccd7b5aSBob Moore * region node/object.
566ccd7b5aSBob Moore *
576ccd7b5aSBob Moore ******************************************************************************/
586ccd7b5aSBob Moore
596ccd7b5aSBob Moore static acpi_status
acpi_ds_create_external_region(acpi_status lookup_status,union acpi_parse_object * op,char * path,struct acpi_walk_state * walk_state,struct acpi_namespace_node ** node)606ccd7b5aSBob Moore acpi_ds_create_external_region(acpi_status lookup_status,
616ccd7b5aSBob Moore union acpi_parse_object *op,
626ccd7b5aSBob Moore char *path,
636ccd7b5aSBob Moore struct acpi_walk_state *walk_state,
646ccd7b5aSBob Moore struct acpi_namespace_node **node)
656ccd7b5aSBob Moore {
666ccd7b5aSBob Moore acpi_status status;
676ccd7b5aSBob Moore union acpi_operand_object *obj_desc;
686ccd7b5aSBob Moore
696ccd7b5aSBob Moore if (lookup_status != AE_NOT_FOUND) {
706ccd7b5aSBob Moore return (lookup_status);
716ccd7b5aSBob Moore }
726ccd7b5aSBob Moore
736ccd7b5aSBob Moore /*
746ccd7b5aSBob Moore * Table disassembly:
756ccd7b5aSBob Moore * operation_region not found. Generate an External for it, and
766ccd7b5aSBob Moore * insert the name into the namespace.
776ccd7b5aSBob Moore */
785af2b635SBob Moore acpi_dm_add_op_to_external_list(op, path, ACPI_TYPE_REGION, 0, 0);
791fad8738SBob Moore
806ccd7b5aSBob Moore status = acpi_ns_lookup(walk_state->scope_info, path, ACPI_TYPE_REGION,
816ccd7b5aSBob Moore ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT,
826ccd7b5aSBob Moore walk_state, node);
836ccd7b5aSBob Moore if (ACPI_FAILURE(status)) {
846ccd7b5aSBob Moore return (status);
856ccd7b5aSBob Moore }
866ccd7b5aSBob Moore
876ccd7b5aSBob Moore /* Must create and install a region object for the new node */
886ccd7b5aSBob Moore
896ccd7b5aSBob Moore obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
906ccd7b5aSBob Moore if (!obj_desc) {
916ccd7b5aSBob Moore return (AE_NO_MEMORY);
926ccd7b5aSBob Moore }
936ccd7b5aSBob Moore
946ccd7b5aSBob Moore obj_desc->region.node = *node;
956ccd7b5aSBob Moore status = acpi_ns_attach_object(*node, obj_desc, ACPI_TYPE_REGION);
966ccd7b5aSBob Moore return (status);
976ccd7b5aSBob Moore }
986ccd7b5aSBob Moore #endif
996ccd7b5aSBob Moore
10095b482a8SLen Brown /*******************************************************************************
10195b482a8SLen Brown *
10295b482a8SLen Brown * FUNCTION: acpi_ds_create_buffer_field
10395b482a8SLen Brown *
104ba494beeSBob Moore * PARAMETERS: op - Current parse op (create_XXField)
10595b482a8SLen Brown * walk_state - Current state
10695b482a8SLen Brown *
10795b482a8SLen Brown * RETURN: Status
10895b482a8SLen Brown *
10995b482a8SLen Brown * DESCRIPTION: Execute the create_field operators:
11095b482a8SLen Brown * create_bit_field_op,
11195b482a8SLen Brown * create_byte_field_op,
11295b482a8SLen Brown * create_word_field_op,
11395b482a8SLen Brown * create_dword_field_op,
11495b482a8SLen Brown * create_qword_field_op,
11595b482a8SLen Brown * create_field_op (all of which define a field in a buffer)
11695b482a8SLen Brown *
11795b482a8SLen Brown ******************************************************************************/
11895b482a8SLen Brown
11995b482a8SLen Brown acpi_status
acpi_ds_create_buffer_field(union acpi_parse_object * op,struct acpi_walk_state * walk_state)12095b482a8SLen Brown acpi_ds_create_buffer_field(union acpi_parse_object *op,
12195b482a8SLen Brown struct acpi_walk_state *walk_state)
12295b482a8SLen Brown {
12395b482a8SLen Brown union acpi_parse_object *arg;
12495b482a8SLen Brown struct acpi_namespace_node *node;
12595b482a8SLen Brown acpi_status status;
12695b482a8SLen Brown union acpi_operand_object *obj_desc;
12795b482a8SLen Brown union acpi_operand_object *second_desc = NULL;
12895b482a8SLen Brown u32 flags;
12995b482a8SLen Brown
13095b482a8SLen Brown ACPI_FUNCTION_TRACE(ds_create_buffer_field);
13195b482a8SLen Brown
13295b482a8SLen Brown /*
13395b482a8SLen Brown * Get the name_string argument (name of the new buffer_field)
13495b482a8SLen Brown */
13595b482a8SLen Brown if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
13695b482a8SLen Brown
13795b482a8SLen Brown /* For create_field, name is the 4th argument */
13895b482a8SLen Brown
13995b482a8SLen Brown arg = acpi_ps_get_arg(op, 3);
14095b482a8SLen Brown } else {
141ba494beeSBob Moore /* For all other create_XXXField operators, name is the 3rd argument */
14295b482a8SLen Brown
14395b482a8SLen Brown arg = acpi_ps_get_arg(op, 2);
14495b482a8SLen Brown }
14595b482a8SLen Brown
14695b482a8SLen Brown if (!arg) {
14795b482a8SLen Brown return_ACPI_STATUS(AE_AML_NO_OPERAND);
14895b482a8SLen Brown }
14995b482a8SLen Brown
15095b482a8SLen Brown if (walk_state->deferred_node) {
15195b482a8SLen Brown node = walk_state->deferred_node;
15295b482a8SLen Brown } else {
15395b482a8SLen Brown /* Execute flag should always be set when this function is entered */
15495b482a8SLen Brown
15595b482a8SLen Brown if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
156376a588cSBob Moore ACPI_ERROR((AE_INFO, "Parse execute mode is not set"));
15795b482a8SLen Brown return_ACPI_STATUS(AE_AML_INTERNAL);
15895b482a8SLen Brown }
15995b482a8SLen Brown
16095b482a8SLen Brown /* Creating new namespace node, should not already exist */
16195b482a8SLen Brown
16295b482a8SLen Brown flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
16395b482a8SLen Brown ACPI_NS_ERROR_IF_FOUND;
16495b482a8SLen Brown
1657f0c826aSLin Ming /*
1667f0c826aSLin Ming * Mark node temporary if we are executing a normal control
1677f0c826aSLin Ming * method. (Don't mark if this is a module-level code method)
1687f0c826aSLin Ming */
1697f0c826aSLin Ming if (walk_state->method_node &&
1707f0c826aSLin Ming !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
17195b482a8SLen Brown flags |= ACPI_NS_TEMPORARY;
17295b482a8SLen Brown }
17395b482a8SLen Brown
17495b482a8SLen Brown /* Enter the name_string into the namespace */
17595b482a8SLen Brown
1761fad8738SBob Moore status = acpi_ns_lookup(walk_state->scope_info,
17795b482a8SLen Brown arg->common.value.string, ACPI_TYPE_ANY,
1781fad8738SBob Moore ACPI_IMODE_LOAD_PASS1, flags,
1791fad8738SBob Moore walk_state, &node);
180034fdaa5SErik Kaneda if ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE)
181034fdaa5SErik Kaneda && status == AE_ALREADY_EXISTS) {
182034fdaa5SErik Kaneda status = AE_OK;
183034fdaa5SErik Kaneda } else if (ACPI_FAILURE(status)) {
18416ccf829SBob Moore ACPI_ERROR_NAMESPACE(walk_state->scope_info,
18516ccf829SBob Moore arg->common.value.string, status);
18695b482a8SLen Brown return_ACPI_STATUS(status);
18795b482a8SLen Brown }
18895b482a8SLen Brown }
18995b482a8SLen Brown
19095b482a8SLen Brown /*
19195b482a8SLen Brown * We could put the returned object (Node) on the object stack for later,
19295b482a8SLen Brown * but for now, we will put it in the "op" object that the parser uses,
19395b482a8SLen Brown * so we can get it again at the end of this scope.
19495b482a8SLen Brown */
19595b482a8SLen Brown op->common.node = node;
19695b482a8SLen Brown
19795b482a8SLen Brown /*
19895b482a8SLen Brown * If there is no object attached to the node, this node was just created
19995b482a8SLen Brown * and we need to create the field object. Otherwise, this was a lookup
20095b482a8SLen Brown * of an existing node and we don't want to create the field object again.
20195b482a8SLen Brown */
20295b482a8SLen Brown obj_desc = acpi_ns_get_attached_object(node);
20395b482a8SLen Brown if (obj_desc) {
20495b482a8SLen Brown return_ACPI_STATUS(AE_OK);
20595b482a8SLen Brown }
20695b482a8SLen Brown
20795b482a8SLen Brown /*
20895b482a8SLen Brown * The Field definition is not fully parsed at this time.
20995b482a8SLen Brown * (We must save the address of the AML for the buffer and index operands)
21095b482a8SLen Brown */
21195b482a8SLen Brown
21295b482a8SLen Brown /* Create the buffer field object */
21395b482a8SLen Brown
21495b482a8SLen Brown obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER_FIELD);
21595b482a8SLen Brown if (!obj_desc) {
21695b482a8SLen Brown status = AE_NO_MEMORY;
21795b482a8SLen Brown goto cleanup;
21895b482a8SLen Brown }
21995b482a8SLen Brown
22095b482a8SLen Brown /*
2211fad8738SBob Moore * Remember location in AML stream of the field unit opcode and operands
2221fad8738SBob Moore * -- since the buffer and index operands must be evaluated.
22395b482a8SLen Brown */
22495b482a8SLen Brown second_desc = obj_desc->common.next_object;
22595b482a8SLen Brown second_desc->extra.aml_start = op->named.data;
22695b482a8SLen Brown second_desc->extra.aml_length = op->named.length;
22795b482a8SLen Brown obj_desc->buffer_field.node = node;
22895b482a8SLen Brown
22995b482a8SLen Brown /* Attach constructed field descriptors to parent node */
23095b482a8SLen Brown
23195b482a8SLen Brown status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_BUFFER_FIELD);
23295b482a8SLen Brown if (ACPI_FAILURE(status)) {
23395b482a8SLen Brown goto cleanup;
23495b482a8SLen Brown }
23595b482a8SLen Brown
23695b482a8SLen Brown cleanup:
23795b482a8SLen Brown
23895b482a8SLen Brown /* Remove local reference to the object */
23995b482a8SLen Brown
24095b482a8SLen Brown acpi_ut_remove_reference(obj_desc);
24195b482a8SLen Brown return_ACPI_STATUS(status);
24295b482a8SLen Brown }
24395b482a8SLen Brown
24495b482a8SLen Brown /*******************************************************************************
24595b482a8SLen Brown *
24695b482a8SLen Brown * FUNCTION: acpi_ds_get_field_names
24795b482a8SLen Brown *
248ba494beeSBob Moore * PARAMETERS: info - create_field info structure
2495ddbd771SErik Kaneda * walk_state - Current method state
250ba494beeSBob Moore * arg - First parser arg for the field name list
25195b482a8SLen Brown *
25295b482a8SLen Brown * RETURN: Status
25395b482a8SLen Brown *
25495b482a8SLen Brown * DESCRIPTION: Process all named fields in a field declaration. Names are
25595b482a8SLen Brown * entered into the namespace.
25695b482a8SLen Brown *
25795b482a8SLen Brown ******************************************************************************/
25895b482a8SLen Brown
25995b482a8SLen Brown static acpi_status
acpi_ds_get_field_names(struct acpi_create_field_info * info,struct acpi_walk_state * walk_state,union acpi_parse_object * arg)26095b482a8SLen Brown acpi_ds_get_field_names(struct acpi_create_field_info *info,
26195b482a8SLen Brown struct acpi_walk_state *walk_state,
26295b482a8SLen Brown union acpi_parse_object *arg)
26395b482a8SLen Brown {
26495b482a8SLen Brown acpi_status status;
2655df7e6cbSBob Moore u64 position;
2669ce81784SBob Moore union acpi_parse_object *child;
26795b482a8SLen Brown
26877d4e096SErik Schmauss #ifdef ACPI_EXEC_APP
26977d4e096SErik Schmauss union acpi_operand_object *result_desc;
27077d4e096SErik Schmauss union acpi_operand_object *obj_desc;
27177d4e096SErik Schmauss char *name_path;
27277d4e096SErik Schmauss #endif
27377d4e096SErik Schmauss
27495b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info);
27595b482a8SLen Brown
27695b482a8SLen Brown /* First field starts at bit zero */
27795b482a8SLen Brown
27895b482a8SLen Brown info->field_bit_position = 0;
27995b482a8SLen Brown
28095b482a8SLen Brown /* Process all elements in the field list (of parse nodes) */
28195b482a8SLen Brown
28295b482a8SLen Brown while (arg) {
28395b482a8SLen Brown /*
2849ce81784SBob Moore * Four types of field elements are handled:
285ba494beeSBob Moore * 1) name - Enters a new named field into the namespace
286ba494beeSBob Moore * 2) offset - specifies a bit offset
2879ce81784SBob Moore * 3) access_as - changes the access mode/attributes
288ba494beeSBob Moore * 4) connection - Associate a resource template with the field
28995b482a8SLen Brown */
29095b482a8SLen Brown switch (arg->common.aml_opcode) {
29195b482a8SLen Brown case AML_INT_RESERVEDFIELD_OP:
29295b482a8SLen Brown
2931fad8738SBob Moore position = (u64)info->field_bit_position +
2941fad8738SBob Moore (u64)arg->common.value.size;
29595b482a8SLen Brown
29695b482a8SLen Brown if (position > ACPI_UINT32_MAX) {
29795b482a8SLen Brown ACPI_ERROR((AE_INFO,
29895b482a8SLen Brown "Bit offset within field too large (> 0xFFFFFFFF)"));
29995b482a8SLen Brown return_ACPI_STATUS(AE_SUPPORT);
30095b482a8SLen Brown }
30195b482a8SLen Brown
30295b482a8SLen Brown info->field_bit_position = (u32) position;
30395b482a8SLen Brown break;
30495b482a8SLen Brown
30595b482a8SLen Brown case AML_INT_ACCESSFIELD_OP:
3069ce81784SBob Moore case AML_INT_EXTACCESSFIELD_OP:
30795b482a8SLen Brown /*
3089ce81784SBob Moore * Get new access_type, access_attribute, and access_length fields
3099ce81784SBob Moore * -- to be used for all field units that follow, until the
3109ce81784SBob Moore * end-of-field or another access_as keyword is encountered.
3119ce81784SBob Moore * NOTE. These three bytes are encoded in the integer value
3129ce81784SBob Moore * of the parseop for convenience.
31395b482a8SLen Brown *
31495b482a8SLen Brown * In field_flags, preserve the flag bits other than the
3159ce81784SBob Moore * ACCESS_TYPE bits.
31695b482a8SLen Brown */
3179ce81784SBob Moore
3189ce81784SBob Moore /* access_type (byte_acc, word_acc, etc.) */
3199ce81784SBob Moore
32095b482a8SLen Brown info->field_flags = (u8)
32195b482a8SLen Brown ((info->
32295b482a8SLen Brown field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
3239ce81784SBob Moore ((u8)((u32)(arg->common.value.integer & 0x07))));
32495b482a8SLen Brown
3259ce81784SBob Moore /* access_attribute (attrib_quick, attrib_byte, etc.) */
3269ce81784SBob Moore
3271fad8738SBob Moore info->attribute = (u8)
3281fad8738SBob Moore ((arg->common.value.integer >> 8) & 0xFF);
3299ce81784SBob Moore
3309ce81784SBob Moore /* access_length (for serial/buffer protocols) */
3319ce81784SBob Moore
3321fad8738SBob Moore info->access_length = (u8)
3331fad8738SBob Moore ((arg->common.value.integer >> 16) & 0xFF);
3349ce81784SBob Moore break;
3359ce81784SBob Moore
3369ce81784SBob Moore case AML_INT_CONNECTION_OP:
3379ce81784SBob Moore /*
3389ce81784SBob Moore * Clear any previous connection. New connection is used for all
3399ce81784SBob Moore * fields that follow, similar to access_as
3409ce81784SBob Moore */
3419ce81784SBob Moore info->resource_buffer = NULL;
3429ce81784SBob Moore info->connection_node = NULL;
34375ec6e55SBob Moore info->pin_number_index = 0;
3449ce81784SBob Moore
3459ce81784SBob Moore /*
3469ce81784SBob Moore * A Connection() is either an actual resource descriptor (buffer)
3479ce81784SBob Moore * or a named reference to a resource template
3489ce81784SBob Moore */
3499ce81784SBob Moore child = arg->common.value.arg;
3509ce81784SBob Moore if (child->common.aml_opcode == AML_INT_BYTELIST_OP) {
3519ce81784SBob Moore info->resource_buffer = child->named.data;
3529ce81784SBob Moore info->resource_length =
3539ce81784SBob Moore (u16)child->named.value.integer;
3549ce81784SBob Moore } else {
3559ce81784SBob Moore /* Lookup the Connection() namepath, it should already exist */
3569ce81784SBob Moore
3579ce81784SBob Moore status = acpi_ns_lookup(walk_state->scope_info,
3589ce81784SBob Moore child->common.value.
3599ce81784SBob Moore name, ACPI_TYPE_ANY,
3609ce81784SBob Moore ACPI_IMODE_EXECUTE,
3619ce81784SBob Moore ACPI_NS_DONT_OPEN_SCOPE,
3629ce81784SBob Moore walk_state,
3639ce81784SBob Moore &info->connection_node);
3649ce81784SBob Moore if (ACPI_FAILURE(status)) {
36516ccf829SBob Moore ACPI_ERROR_NAMESPACE(walk_state->
36616ccf829SBob Moore scope_info,
36716ccf829SBob Moore child->common.
3689ce81784SBob Moore value.name,
3699ce81784SBob Moore status);
3709ce81784SBob Moore return_ACPI_STATUS(status);
3719ce81784SBob Moore }
3729ce81784SBob Moore }
37395b482a8SLen Brown break;
37495b482a8SLen Brown
37595b482a8SLen Brown case AML_INT_NAMEDFIELD_OP:
37695b482a8SLen Brown
37795b482a8SLen Brown /* Lookup the name, it should already exist */
37895b482a8SLen Brown
37995b482a8SLen Brown status = acpi_ns_lookup(walk_state->scope_info,
38095b482a8SLen Brown (char *)&arg->named.name,
38195b482a8SLen Brown info->field_type,
38295b482a8SLen Brown ACPI_IMODE_EXECUTE,
38395b482a8SLen Brown ACPI_NS_DONT_OPEN_SCOPE,
38495b482a8SLen Brown walk_state, &info->field_node);
38595b482a8SLen Brown if (ACPI_FAILURE(status)) {
38616ccf829SBob Moore ACPI_ERROR_NAMESPACE(walk_state->scope_info,
38716ccf829SBob Moore (char *)&arg->named.name,
38895b482a8SLen Brown status);
38995b482a8SLen Brown return_ACPI_STATUS(status);
39095b482a8SLen Brown } else {
39195b482a8SLen Brown arg->common.node = info->field_node;
39295b482a8SLen Brown info->field_bit_length = arg->common.value.size;
39395b482a8SLen Brown
39495b482a8SLen Brown /*
39595b482a8SLen Brown * If there is no object attached to the node, this node was
39695b482a8SLen Brown * just created and we need to create the field object.
39795b482a8SLen Brown * Otherwise, this was a lookup of an existing node and we
39895b482a8SLen Brown * don't want to create the field object again.
39995b482a8SLen Brown */
40095b482a8SLen Brown if (!acpi_ns_get_attached_object
40195b482a8SLen Brown (info->field_node)) {
40295b482a8SLen Brown status = acpi_ex_prep_field_value(info);
40395b482a8SLen Brown if (ACPI_FAILURE(status)) {
40495b482a8SLen Brown return_ACPI_STATUS(status);
40595b482a8SLen Brown }
40677d4e096SErik Schmauss #ifdef ACPI_EXEC_APP
40777d4e096SErik Schmauss name_path =
40877d4e096SErik Schmauss acpi_ns_get_external_pathname(info->
40977d4e096SErik Schmauss field_node);
41077d4e096SErik Schmauss if (ACPI_SUCCESS
41177d4e096SErik Schmauss (ae_lookup_init_file_entry
41202b04f10SErik Schmauss (name_path, &obj_desc))) {
41377d4e096SErik Schmauss acpi_ex_write_data_to_field
41477d4e096SErik Schmauss (obj_desc,
41577d4e096SErik Schmauss acpi_ns_get_attached_object
41677d4e096SErik Schmauss (info->field_node),
41777d4e096SErik Schmauss &result_desc);
41802b04f10SErik Schmauss acpi_ut_remove_reference
41902b04f10SErik Schmauss (obj_desc);
42077d4e096SErik Schmauss }
4218b66fcfdSBob Moore ACPI_FREE(name_path);
42277d4e096SErik Schmauss #endif
42395b482a8SLen Brown }
42495b482a8SLen Brown }
42595b482a8SLen Brown
42695b482a8SLen Brown /* Keep track of bit position for the next field */
42795b482a8SLen Brown
4281fad8738SBob Moore position = (u64)info->field_bit_position +
4291fad8738SBob Moore (u64)arg->common.value.size;
43095b482a8SLen Brown
43195b482a8SLen Brown if (position > ACPI_UINT32_MAX) {
43295b482a8SLen Brown ACPI_ERROR((AE_INFO,
43395b482a8SLen Brown "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)",
43495b482a8SLen Brown ACPI_CAST_PTR(char,
43595b482a8SLen Brown &info->field_node->
43695b482a8SLen Brown name)));
43795b482a8SLen Brown return_ACPI_STATUS(AE_SUPPORT);
43895b482a8SLen Brown }
43995b482a8SLen Brown
44095b482a8SLen Brown info->field_bit_position += info->field_bit_length;
44175ec6e55SBob Moore info->pin_number_index++; /* Index relative to previous Connection() */
44295b482a8SLen Brown break;
44395b482a8SLen Brown
44495b482a8SLen Brown default:
44595b482a8SLen Brown
44695b482a8SLen Brown ACPI_ERROR((AE_INFO,
447f6a22b0bSBob Moore "Invalid opcode in field list: 0x%X",
44895b482a8SLen Brown arg->common.aml_opcode));
44995b482a8SLen Brown return_ACPI_STATUS(AE_AML_BAD_OPCODE);
45095b482a8SLen Brown }
45195b482a8SLen Brown
45295b482a8SLen Brown arg = arg->common.next;
45395b482a8SLen Brown }
45495b482a8SLen Brown
45595b482a8SLen Brown return_ACPI_STATUS(AE_OK);
45695b482a8SLen Brown }
45795b482a8SLen Brown
45895b482a8SLen Brown /*******************************************************************************
45995b482a8SLen Brown *
46095b482a8SLen Brown * FUNCTION: acpi_ds_create_field
46195b482a8SLen Brown *
462ba494beeSBob Moore * PARAMETERS: op - Op containing the Field definition and args
46395b482a8SLen Brown * region_node - Object for the containing Operation Region
46495b482a8SLen Brown * ` walk_state - Current method state
46595b482a8SLen Brown *
46695b482a8SLen Brown * RETURN: Status
46795b482a8SLen Brown *
46895b482a8SLen Brown * DESCRIPTION: Create a new field in the specified operation region
46995b482a8SLen Brown *
47095b482a8SLen Brown ******************************************************************************/
47195b482a8SLen Brown
47295b482a8SLen Brown acpi_status
acpi_ds_create_field(union acpi_parse_object * op,struct acpi_namespace_node * region_node,struct acpi_walk_state * walk_state)47395b482a8SLen Brown acpi_ds_create_field(union acpi_parse_object *op,
47495b482a8SLen Brown struct acpi_namespace_node *region_node,
47595b482a8SLen Brown struct acpi_walk_state *walk_state)
47695b482a8SLen Brown {
47795b482a8SLen Brown acpi_status status;
47895b482a8SLen Brown union acpi_parse_object *arg;
47995b482a8SLen Brown struct acpi_create_field_info info;
48095b482a8SLen Brown
48195b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ds_create_field, op);
48295b482a8SLen Brown
48395b482a8SLen Brown /* First arg is the name of the parent op_region (must already exist) */
48495b482a8SLen Brown
48595b482a8SLen Brown arg = op->common.value.arg;
4866ccd7b5aSBob Moore
48795b482a8SLen Brown if (!region_node) {
48895b482a8SLen Brown status =
48995b482a8SLen Brown acpi_ns_lookup(walk_state->scope_info,
49095b482a8SLen Brown arg->common.value.name, ACPI_TYPE_REGION,
49195b482a8SLen Brown ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
49295b482a8SLen Brown walk_state, ®ion_node);
4936ccd7b5aSBob Moore #ifdef ACPI_ASL_COMPILER
4946ccd7b5aSBob Moore status = acpi_ds_create_external_region(status, arg,
4956ccd7b5aSBob Moore arg->common.value.name,
4966ccd7b5aSBob Moore walk_state,
4976ccd7b5aSBob Moore ®ion_node);
4986ccd7b5aSBob Moore #endif
49995b482a8SLen Brown if (ACPI_FAILURE(status)) {
50016ccf829SBob Moore ACPI_ERROR_NAMESPACE(walk_state->scope_info,
50116ccf829SBob Moore arg->common.value.name, status);
50295b482a8SLen Brown return_ACPI_STATUS(status);
50395b482a8SLen Brown }
50495b482a8SLen Brown }
50595b482a8SLen Brown
5064fa4616eSBob Moore memset(&info, 0, sizeof(struct acpi_create_field_info));
5079ce81784SBob Moore
50895b482a8SLen Brown /* Second arg is the field flags */
50995b482a8SLen Brown
51095b482a8SLen Brown arg = arg->common.next;
51195b482a8SLen Brown info.field_flags = (u8) arg->common.value.integer;
51295b482a8SLen Brown info.attribute = 0;
51395b482a8SLen Brown
51495b482a8SLen Brown /* Each remaining arg is a Named Field */
51595b482a8SLen Brown
51695b482a8SLen Brown info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD;
51795b482a8SLen Brown info.region_node = region_node;
51895b482a8SLen Brown
51995b482a8SLen Brown status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
5206bfe5344SErik Kaneda if (ACPI_FAILURE(status)) {
5216bfe5344SErik Kaneda return_ACPI_STATUS(status);
5226bfe5344SErik Kaneda }
5236bfe5344SErik Kaneda
524aa6ec56bSErik Schmauss if (info.region_node->object->region.space_id ==
5256bfe5344SErik Kaneda ACPI_ADR_SPACE_PLATFORM_COMM) {
5266bfe5344SErik Kaneda region_node->object->field.internal_pcc_buffer =
527aa6ec56bSErik Schmauss ACPI_ALLOCATE_ZEROED(info.region_node->object->region.
5286bfe5344SErik Kaneda length);
5296bfe5344SErik Kaneda if (!region_node->object->field.internal_pcc_buffer) {
530aa6ec56bSErik Schmauss return_ACPI_STATUS(AE_NO_MEMORY);
531aa6ec56bSErik Schmauss }
5326bfe5344SErik Kaneda }
5336bfe5344SErik Kaneda
53495b482a8SLen Brown return_ACPI_STATUS(status);
53595b482a8SLen Brown }
53695b482a8SLen Brown
53795b482a8SLen Brown /*******************************************************************************
53895b482a8SLen Brown *
53995b482a8SLen Brown * FUNCTION: acpi_ds_init_field_objects
54095b482a8SLen Brown *
541ba494beeSBob Moore * PARAMETERS: op - Op containing the Field definition and args
54295b482a8SLen Brown * ` walk_state - Current method state
54395b482a8SLen Brown *
54495b482a8SLen Brown * RETURN: Status
54595b482a8SLen Brown *
54695b482a8SLen Brown * DESCRIPTION: For each "Field Unit" name in the argument list that is
54795b482a8SLen Brown * part of the field declaration, enter the name into the
54895b482a8SLen Brown * namespace.
54995b482a8SLen Brown *
55095b482a8SLen Brown ******************************************************************************/
55195b482a8SLen Brown
55295b482a8SLen Brown acpi_status
acpi_ds_init_field_objects(union acpi_parse_object * op,struct acpi_walk_state * walk_state)55395b482a8SLen Brown acpi_ds_init_field_objects(union acpi_parse_object *op,
55495b482a8SLen Brown struct acpi_walk_state *walk_state)
55595b482a8SLen Brown {
55695b482a8SLen Brown acpi_status status;
55795b482a8SLen Brown union acpi_parse_object *arg = NULL;
55895b482a8SLen Brown struct acpi_namespace_node *node;
55995b482a8SLen Brown u8 type = 0;
56095b482a8SLen Brown u32 flags;
56195b482a8SLen Brown
56295b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op);
56395b482a8SLen Brown
56495b482a8SLen Brown /* Execute flag should always be set when this function is entered */
56595b482a8SLen Brown
56695b482a8SLen Brown if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
56795b482a8SLen Brown if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) {
56895b482a8SLen Brown
56995b482a8SLen Brown /* bank_field Op is deferred, just return OK */
57095b482a8SLen Brown
57195b482a8SLen Brown return_ACPI_STATUS(AE_OK);
57295b482a8SLen Brown }
57395b482a8SLen Brown
574376a588cSBob Moore ACPI_ERROR((AE_INFO, "Parse deferred mode is not set"));
57595b482a8SLen Brown return_ACPI_STATUS(AE_AML_INTERNAL);
57695b482a8SLen Brown }
57795b482a8SLen Brown
57895b482a8SLen Brown /*
57995b482a8SLen Brown * Get the field_list argument for this opcode. This is the start of the
58095b482a8SLen Brown * list of field elements.
58195b482a8SLen Brown */
58295b482a8SLen Brown switch (walk_state->opcode) {
58395b482a8SLen Brown case AML_FIELD_OP:
5841d1ea1b7SChao Guan
58595b482a8SLen Brown arg = acpi_ps_get_arg(op, 2);
58695b482a8SLen Brown type = ACPI_TYPE_LOCAL_REGION_FIELD;
58795b482a8SLen Brown break;
58895b482a8SLen Brown
58995b482a8SLen Brown case AML_BANK_FIELD_OP:
5901d1ea1b7SChao Guan
59195b482a8SLen Brown arg = acpi_ps_get_arg(op, 4);
59295b482a8SLen Brown type = ACPI_TYPE_LOCAL_BANK_FIELD;
59395b482a8SLen Brown break;
59495b482a8SLen Brown
59595b482a8SLen Brown case AML_INDEX_FIELD_OP:
5961d1ea1b7SChao Guan
59795b482a8SLen Brown arg = acpi_ps_get_arg(op, 3);
59895b482a8SLen Brown type = ACPI_TYPE_LOCAL_INDEX_FIELD;
59995b482a8SLen Brown break;
60095b482a8SLen Brown
60195b482a8SLen Brown default:
6021d1ea1b7SChao Guan
60395b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER);
60495b482a8SLen Brown }
60595b482a8SLen Brown
60695b482a8SLen Brown /* Creating new namespace node(s), should not already exist */
60795b482a8SLen Brown
60895b482a8SLen Brown flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
60995b482a8SLen Brown ACPI_NS_ERROR_IF_FOUND;
61095b482a8SLen Brown
6117f0c826aSLin Ming /*
6127f0c826aSLin Ming * Mark node(s) temporary if we are executing a normal control
6137f0c826aSLin Ming * method. (Don't mark if this is a module-level code method)
6147f0c826aSLin Ming */
6157f0c826aSLin Ming if (walk_state->method_node &&
6167f0c826aSLin Ming !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
61795b482a8SLen Brown flags |= ACPI_NS_TEMPORARY;
61895b482a8SLen Brown }
61977d4e096SErik Schmauss #ifdef ACPI_EXEC_APP
62077d4e096SErik Schmauss flags |= ACPI_NS_OVERRIDE_IF_FOUND;
62177d4e096SErik Schmauss #endif
62295b482a8SLen Brown /*
62395b482a8SLen Brown * Walk the list of entries in the field_list
62495b482a8SLen Brown * Note: field_list can be of zero length. In this case, Arg will be NULL.
62595b482a8SLen Brown */
62695b482a8SLen Brown while (arg) {
62795b482a8SLen Brown /*
6289ce81784SBob Moore * Ignore OFFSET/ACCESSAS/CONNECTION terms here; we are only interested
6299ce81784SBob Moore * in the field names in order to enter them into the namespace.
63095b482a8SLen Brown */
63195b482a8SLen Brown if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
63295b482a8SLen Brown status = acpi_ns_lookup(walk_state->scope_info,
63395b482a8SLen Brown (char *)&arg->named.name, type,
63495b482a8SLen Brown ACPI_IMODE_LOAD_PASS1, flags,
63595b482a8SLen Brown walk_state, &node);
63695b482a8SLen Brown if (ACPI_FAILURE(status)) {
63716ccf829SBob Moore ACPI_ERROR_NAMESPACE(walk_state->scope_info,
63816ccf829SBob Moore (char *)&arg->named.name,
63995b482a8SLen Brown status);
64095b482a8SLen Brown if (status != AE_ALREADY_EXISTS) {
64195b482a8SLen Brown return_ACPI_STATUS(status);
64295b482a8SLen Brown }
64395b482a8SLen Brown
64495b482a8SLen Brown /* Name already exists, just ignore this error */
64595b482a8SLen Brown }
64695b482a8SLen Brown
64795b482a8SLen Brown arg->common.node = node;
64895b482a8SLen Brown }
64995b482a8SLen Brown
65095b482a8SLen Brown /* Get the next field element in the list */
65195b482a8SLen Brown
65295b482a8SLen Brown arg = arg->common.next;
65395b482a8SLen Brown }
65495b482a8SLen Brown
65595b482a8SLen Brown return_ACPI_STATUS(AE_OK);
65695b482a8SLen Brown }
65795b482a8SLen Brown
65895b482a8SLen Brown /*******************************************************************************
65995b482a8SLen Brown *
66095b482a8SLen Brown * FUNCTION: acpi_ds_create_bank_field
66195b482a8SLen Brown *
662ba494beeSBob Moore * PARAMETERS: op - Op containing the Field definition and args
66395b482a8SLen Brown * region_node - Object for the containing Operation Region
66495b482a8SLen Brown * walk_state - Current method state
66595b482a8SLen Brown *
66695b482a8SLen Brown * RETURN: Status
66795b482a8SLen Brown *
66895b482a8SLen Brown * DESCRIPTION: Create a new bank field in the specified operation region
66995b482a8SLen Brown *
67095b482a8SLen Brown ******************************************************************************/
67195b482a8SLen Brown
67295b482a8SLen Brown acpi_status
acpi_ds_create_bank_field(union acpi_parse_object * op,struct acpi_namespace_node * region_node,struct acpi_walk_state * walk_state)67395b482a8SLen Brown acpi_ds_create_bank_field(union acpi_parse_object *op,
67495b482a8SLen Brown struct acpi_namespace_node *region_node,
67595b482a8SLen Brown struct acpi_walk_state *walk_state)
67695b482a8SLen Brown {
67795b482a8SLen Brown acpi_status status;
67895b482a8SLen Brown union acpi_parse_object *arg;
67995b482a8SLen Brown struct acpi_create_field_info info;
68095b482a8SLen Brown
68195b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op);
68295b482a8SLen Brown
68395b482a8SLen Brown /* First arg is the name of the parent op_region (must already exist) */
68495b482a8SLen Brown
68595b482a8SLen Brown arg = op->common.value.arg;
68695b482a8SLen Brown if (!region_node) {
68795b482a8SLen Brown status =
68895b482a8SLen Brown acpi_ns_lookup(walk_state->scope_info,
68995b482a8SLen Brown arg->common.value.name, ACPI_TYPE_REGION,
69095b482a8SLen Brown ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
69195b482a8SLen Brown walk_state, ®ion_node);
6926ccd7b5aSBob Moore #ifdef ACPI_ASL_COMPILER
6936ccd7b5aSBob Moore status = acpi_ds_create_external_region(status, arg,
6946ccd7b5aSBob Moore arg->common.value.name,
6956ccd7b5aSBob Moore walk_state,
6966ccd7b5aSBob Moore ®ion_node);
6976ccd7b5aSBob Moore #endif
69895b482a8SLen Brown if (ACPI_FAILURE(status)) {
69916ccf829SBob Moore ACPI_ERROR_NAMESPACE(walk_state->scope_info,
70016ccf829SBob Moore arg->common.value.name, status);
70195b482a8SLen Brown return_ACPI_STATUS(status);
70295b482a8SLen Brown }
70395b482a8SLen Brown }
70495b482a8SLen Brown
70595b482a8SLen Brown /* Second arg is the Bank Register (Field) (must already exist) */
70695b482a8SLen Brown
70795b482a8SLen Brown arg = arg->common.next;
70895b482a8SLen Brown status =
70995b482a8SLen Brown acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
71095b482a8SLen Brown ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
71195b482a8SLen Brown ACPI_NS_SEARCH_PARENT, walk_state,
71295b482a8SLen Brown &info.register_node);
71395b482a8SLen Brown if (ACPI_FAILURE(status)) {
71416ccf829SBob Moore ACPI_ERROR_NAMESPACE(walk_state->scope_info,
71516ccf829SBob Moore arg->common.value.string, status);
71695b482a8SLen Brown return_ACPI_STATUS(status);
71795b482a8SLen Brown }
71895b482a8SLen Brown
71995b482a8SLen Brown /*
72095b482a8SLen Brown * Third arg is the bank_value
72195b482a8SLen Brown * This arg is a term_arg, not a constant
72295b482a8SLen Brown * It will be evaluated later, by acpi_ds_eval_bank_field_operands
72395b482a8SLen Brown */
72495b482a8SLen Brown arg = arg->common.next;
72595b482a8SLen Brown
72695b482a8SLen Brown /* Fourth arg is the field flags */
72795b482a8SLen Brown
72895b482a8SLen Brown arg = arg->common.next;
72995b482a8SLen Brown info.field_flags = (u8) arg->common.value.integer;
73095b482a8SLen Brown
73195b482a8SLen Brown /* Each remaining arg is a Named Field */
73295b482a8SLen Brown
73395b482a8SLen Brown info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD;
73495b482a8SLen Brown info.region_node = region_node;
73595b482a8SLen Brown
73695b482a8SLen Brown /*
73795b482a8SLen Brown * Use Info.data_register_node to store bank_field Op
7381fad8738SBob Moore * It's safe because data_register_node will never be used when create
7391fad8738SBob Moore * bank field \we store aml_start and aml_length in the bank_field Op for
7401fad8738SBob Moore * late evaluation. Used in acpi_ex_prep_field_value(Info)
74195b482a8SLen Brown *
7421fad8738SBob Moore * TBD: Or, should we add a field in struct acpi_create_field_info, like
7431fad8738SBob Moore * "void *ParentOp"?
74495b482a8SLen Brown */
74595b482a8SLen Brown info.data_register_node = (struct acpi_namespace_node *)op;
74695b482a8SLen Brown
74795b482a8SLen Brown status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
74895b482a8SLen Brown return_ACPI_STATUS(status);
74995b482a8SLen Brown }
75095b482a8SLen Brown
75195b482a8SLen Brown /*******************************************************************************
75295b482a8SLen Brown *
75395b482a8SLen Brown * FUNCTION: acpi_ds_create_index_field
75495b482a8SLen Brown *
755ba494beeSBob Moore * PARAMETERS: op - Op containing the Field definition and args
75695b482a8SLen Brown * region_node - Object for the containing Operation Region
75795b482a8SLen Brown * ` walk_state - Current method state
75895b482a8SLen Brown *
75995b482a8SLen Brown * RETURN: Status
76095b482a8SLen Brown *
76195b482a8SLen Brown * DESCRIPTION: Create a new index field in the specified operation region
76295b482a8SLen Brown *
76395b482a8SLen Brown ******************************************************************************/
76495b482a8SLen Brown
76595b482a8SLen Brown acpi_status
acpi_ds_create_index_field(union acpi_parse_object * op,struct acpi_namespace_node * region_node,struct acpi_walk_state * walk_state)76695b482a8SLen Brown acpi_ds_create_index_field(union acpi_parse_object *op,
76795b482a8SLen Brown struct acpi_namespace_node *region_node,
76895b482a8SLen Brown struct acpi_walk_state *walk_state)
76995b482a8SLen Brown {
77095b482a8SLen Brown acpi_status status;
77195b482a8SLen Brown union acpi_parse_object *arg;
77295b482a8SLen Brown struct acpi_create_field_info info;
77395b482a8SLen Brown
77495b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op);
77595b482a8SLen Brown
77695b482a8SLen Brown /* First arg is the name of the Index register (must already exist) */
77795b482a8SLen Brown
77895b482a8SLen Brown arg = op->common.value.arg;
77995b482a8SLen Brown status =
78095b482a8SLen Brown acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
78195b482a8SLen Brown ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
78295b482a8SLen Brown ACPI_NS_SEARCH_PARENT, walk_state,
78395b482a8SLen Brown &info.register_node);
78495b482a8SLen Brown if (ACPI_FAILURE(status)) {
78516ccf829SBob Moore ACPI_ERROR_NAMESPACE(walk_state->scope_info,
78616ccf829SBob Moore arg->common.value.string, status);
78795b482a8SLen Brown return_ACPI_STATUS(status);
78895b482a8SLen Brown }
78995b482a8SLen Brown
79095b482a8SLen Brown /* Second arg is the data register (must already exist) */
79195b482a8SLen Brown
79295b482a8SLen Brown arg = arg->common.next;
79395b482a8SLen Brown status =
79495b482a8SLen Brown acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
79595b482a8SLen Brown ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
79695b482a8SLen Brown ACPI_NS_SEARCH_PARENT, walk_state,
79795b482a8SLen Brown &info.data_register_node);
79895b482a8SLen Brown if (ACPI_FAILURE(status)) {
79916ccf829SBob Moore ACPI_ERROR_NAMESPACE(walk_state->scope_info,
80016ccf829SBob Moore arg->common.value.string, status);
80195b482a8SLen Brown return_ACPI_STATUS(status);
80295b482a8SLen Brown }
80395b482a8SLen Brown
80495b482a8SLen Brown /* Next arg is the field flags */
80595b482a8SLen Brown
80695b482a8SLen Brown arg = arg->common.next;
80795b482a8SLen Brown info.field_flags = (u8) arg->common.value.integer;
80895b482a8SLen Brown
80995b482a8SLen Brown /* Each remaining arg is a Named Field */
81095b482a8SLen Brown
81195b482a8SLen Brown info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD;
81295b482a8SLen Brown info.region_node = region_node;
81395b482a8SLen Brown
81495b482a8SLen Brown status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
81595b482a8SLen Brown return_ACPI_STATUS(status);
81695b482a8SLen Brown }
817