195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /******************************************************************************
395b482a8SLen Brown *
495b482a8SLen Brown * Module Name: excreate - Named object creation
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 "acinterp.h"
13e2f7a777SLen Brown #include "amlcode.h"
14e2f7a777SLen Brown #include "acnamesp.h"
1595b482a8SLen Brown
1695b482a8SLen Brown #define _COMPONENT ACPI_EXECUTER
1795b482a8SLen Brown ACPI_MODULE_NAME("excreate")
1895b482a8SLen Brown /*******************************************************************************
1995b482a8SLen Brown *
2095b482a8SLen Brown * FUNCTION: acpi_ex_create_alias
2195b482a8SLen Brown *
2295b482a8SLen Brown * PARAMETERS: walk_state - Current state, contains operands
2395b482a8SLen Brown *
2495b482a8SLen Brown * RETURN: Status
2595b482a8SLen Brown *
2695b482a8SLen Brown * DESCRIPTION: Create a new named alias
2795b482a8SLen Brown *
2895b482a8SLen Brown ******************************************************************************/
acpi_ex_create_alias(struct acpi_walk_state * walk_state)2995b482a8SLen Brown acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
3095b482a8SLen Brown {
3195b482a8SLen Brown struct acpi_namespace_node *target_node;
3295b482a8SLen Brown struct acpi_namespace_node *alias_node;
3395b482a8SLen Brown acpi_status status = AE_OK;
3495b482a8SLen Brown
3595b482a8SLen Brown ACPI_FUNCTION_TRACE(ex_create_alias);
3695b482a8SLen Brown
3795b482a8SLen Brown /* Get the source/alias operands (both namespace nodes) */
3895b482a8SLen Brown
3995b482a8SLen Brown alias_node = (struct acpi_namespace_node *)walk_state->operands[0];
4095b482a8SLen Brown target_node = (struct acpi_namespace_node *)walk_state->operands[1];
4195b482a8SLen Brown
4295b482a8SLen Brown if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) ||
4395b482a8SLen Brown (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
4495b482a8SLen Brown /*
4595b482a8SLen Brown * Dereference an existing alias so that we don't create a chain
4695b482a8SLen Brown * of aliases. With this code, we guarantee that an alias is
4795b482a8SLen Brown * always exactly one level of indirection away from the
4895b482a8SLen Brown * actual aliased name.
4995b482a8SLen Brown */
5095b482a8SLen Brown target_node =
5195b482a8SLen Brown ACPI_CAST_PTR(struct acpi_namespace_node,
5295b482a8SLen Brown target_node->object);
5395b482a8SLen Brown }
5495b482a8SLen Brown
554e6cbe56SAlex James /* Ensure that the target node is valid */
56a5b6e982SBob Moore
574e6cbe56SAlex James if (!target_node) {
584e6cbe56SAlex James return_ACPI_STATUS(AE_NULL_OBJECT);
594e6cbe56SAlex James }
604e6cbe56SAlex James
61a5b6e982SBob Moore /* Construct the alias object (a namespace node) */
62a5b6e982SBob Moore
6395b482a8SLen Brown switch (target_node->type) {
64a5b6e982SBob Moore case ACPI_TYPE_METHOD:
6595b482a8SLen Brown /*
66a5b6e982SBob Moore * Control method aliases need to be differentiated with
67a5b6e982SBob Moore * a special type
6895b482a8SLen Brown */
69a5b6e982SBob Moore alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
70a5b6e982SBob Moore break;
71a5b6e982SBob Moore
72a5b6e982SBob Moore default:
7395b482a8SLen Brown /*
74a5b6e982SBob Moore * All other object types.
75a5b6e982SBob Moore *
7695b482a8SLen Brown * The new alias has the type ALIAS and points to the original
7795b482a8SLen Brown * NS node, not the object itself.
7895b482a8SLen Brown */
7995b482a8SLen Brown alias_node->type = ACPI_TYPE_LOCAL_ALIAS;
8095b482a8SLen Brown alias_node->object =
8195b482a8SLen Brown ACPI_CAST_PTR(union acpi_operand_object, target_node);
8295b482a8SLen Brown break;
8395b482a8SLen Brown }
8495b482a8SLen Brown
8595b482a8SLen Brown /* Since both operands are Nodes, we don't need to delete them */
8695b482a8SLen Brown
87a5b6e982SBob Moore alias_node->object =
88a5b6e982SBob Moore ACPI_CAST_PTR(union acpi_operand_object, target_node);
8995b482a8SLen Brown return_ACPI_STATUS(status);
9095b482a8SLen Brown }
9195b482a8SLen Brown
9295b482a8SLen Brown /*******************************************************************************
9395b482a8SLen Brown *
9495b482a8SLen Brown * FUNCTION: acpi_ex_create_event
9595b482a8SLen Brown *
9695b482a8SLen Brown * PARAMETERS: walk_state - Current state
9795b482a8SLen Brown *
9895b482a8SLen Brown * RETURN: Status
9995b482a8SLen Brown *
10095b482a8SLen Brown * DESCRIPTION: Create a new event object
10195b482a8SLen Brown *
10295b482a8SLen Brown ******************************************************************************/
10395b482a8SLen Brown
acpi_ex_create_event(struct acpi_walk_state * walk_state)10495b482a8SLen Brown acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state)
10595b482a8SLen Brown {
10695b482a8SLen Brown acpi_status status;
10795b482a8SLen Brown union acpi_operand_object *obj_desc;
10895b482a8SLen Brown
10995b482a8SLen Brown ACPI_FUNCTION_TRACE(ex_create_event);
11095b482a8SLen Brown
11195b482a8SLen Brown obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_EVENT);
11295b482a8SLen Brown if (!obj_desc) {
11395b482a8SLen Brown status = AE_NO_MEMORY;
11495b482a8SLen Brown goto cleanup;
11595b482a8SLen Brown }
11695b482a8SLen Brown
11795b482a8SLen Brown /*
11895b482a8SLen Brown * Create the actual OS semaphore, with zero initial units -- meaning
11995b482a8SLen Brown * that the event is created in an unsignalled state
12095b482a8SLen Brown */
12195b482a8SLen Brown status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0,
12295b482a8SLen Brown &obj_desc->event.os_semaphore);
12395b482a8SLen Brown if (ACPI_FAILURE(status)) {
12495b482a8SLen Brown goto cleanup;
12595b482a8SLen Brown }
12695b482a8SLen Brown
12795b482a8SLen Brown /* Attach object to the Node */
12895b482a8SLen Brown
1291fad8738SBob Moore status = acpi_ns_attach_object((struct acpi_namespace_node *)
1301fad8738SBob Moore walk_state->operands[0], obj_desc,
1311fad8738SBob Moore ACPI_TYPE_EVENT);
13295b482a8SLen Brown
13395b482a8SLen Brown cleanup:
13495b482a8SLen Brown /*
13595b482a8SLen Brown * Remove local reference to the object (on error, will cause deletion
13695b482a8SLen Brown * of both object and semaphore if present.)
13795b482a8SLen Brown */
13895b482a8SLen Brown acpi_ut_remove_reference(obj_desc);
13995b482a8SLen Brown return_ACPI_STATUS(status);
14095b482a8SLen Brown }
14195b482a8SLen Brown
14295b482a8SLen Brown /*******************************************************************************
14395b482a8SLen Brown *
14495b482a8SLen Brown * FUNCTION: acpi_ex_create_mutex
14595b482a8SLen Brown *
14695b482a8SLen Brown * PARAMETERS: walk_state - Current state
14795b482a8SLen Brown *
14895b482a8SLen Brown * RETURN: Status
14995b482a8SLen Brown *
15095b482a8SLen Brown * DESCRIPTION: Create a new mutex object
15195b482a8SLen Brown *
15295b482a8SLen Brown * Mutex (Name[0], sync_level[1])
15395b482a8SLen Brown *
15495b482a8SLen Brown ******************************************************************************/
15595b482a8SLen Brown
acpi_ex_create_mutex(struct acpi_walk_state * walk_state)15695b482a8SLen Brown acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)
15795b482a8SLen Brown {
15895b482a8SLen Brown acpi_status status = AE_OK;
15995b482a8SLen Brown union acpi_operand_object *obj_desc;
16095b482a8SLen Brown
16195b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ex_create_mutex, ACPI_WALK_OPERANDS);
16295b482a8SLen Brown
16395b482a8SLen Brown /* Create the new mutex object */
16495b482a8SLen Brown
16595b482a8SLen Brown obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_MUTEX);
16695b482a8SLen Brown if (!obj_desc) {
16795b482a8SLen Brown status = AE_NO_MEMORY;
16895b482a8SLen Brown goto cleanup;
16995b482a8SLen Brown }
17095b482a8SLen Brown
17195b482a8SLen Brown /* Create the actual OS Mutex */
17295b482a8SLen Brown
17395b482a8SLen Brown status = acpi_os_create_mutex(&obj_desc->mutex.os_mutex);
17495b482a8SLen Brown if (ACPI_FAILURE(status)) {
17595b482a8SLen Brown goto cleanup;
17695b482a8SLen Brown }
17795b482a8SLen Brown
17895b482a8SLen Brown /* Init object and attach to NS node */
17995b482a8SLen Brown
1801f86e8c1SLv Zheng obj_desc->mutex.sync_level = (u8)walk_state->operands[1]->integer.value;
18195b482a8SLen Brown obj_desc->mutex.node =
18295b482a8SLen Brown (struct acpi_namespace_node *)walk_state->operands[0];
18395b482a8SLen Brown
18495b482a8SLen Brown status =
18595b482a8SLen Brown acpi_ns_attach_object(obj_desc->mutex.node, obj_desc,
18695b482a8SLen Brown ACPI_TYPE_MUTEX);
18795b482a8SLen Brown
18895b482a8SLen Brown cleanup:
18995b482a8SLen Brown /*
19095b482a8SLen Brown * Remove local reference to the object (on error, will cause deletion
19195b482a8SLen Brown * of both object and semaphore if present.)
19295b482a8SLen Brown */
19395b482a8SLen Brown acpi_ut_remove_reference(obj_desc);
19495b482a8SLen Brown return_ACPI_STATUS(status);
19595b482a8SLen Brown }
19695b482a8SLen Brown
19795b482a8SLen Brown /*******************************************************************************
19895b482a8SLen Brown *
19995b482a8SLen Brown * FUNCTION: acpi_ex_create_region
20095b482a8SLen Brown *
20195b482a8SLen Brown * PARAMETERS: aml_start - Pointer to the region declaration AML
20295b482a8SLen Brown * aml_length - Max length of the declaration AML
203ec463666SBob Moore * space_id - Address space ID for the region
20495b482a8SLen Brown * walk_state - Current state
20595b482a8SLen Brown *
20695b482a8SLen Brown * RETURN: Status
20795b482a8SLen Brown *
20895b482a8SLen Brown * DESCRIPTION: Create a new operation region object
20995b482a8SLen Brown *
21095b482a8SLen Brown ******************************************************************************/
21195b482a8SLen Brown
21295b482a8SLen Brown acpi_status
acpi_ex_create_region(u8 * aml_start,u32 aml_length,u8 space_id,struct acpi_walk_state * walk_state)21395b482a8SLen Brown acpi_ex_create_region(u8 * aml_start,
21495b482a8SLen Brown u32 aml_length,
215ec463666SBob Moore u8 space_id, struct acpi_walk_state *walk_state)
21695b482a8SLen Brown {
21795b482a8SLen Brown acpi_status status;
21895b482a8SLen Brown union acpi_operand_object *obj_desc;
21995b482a8SLen Brown struct acpi_namespace_node *node;
22095b482a8SLen Brown union acpi_operand_object *region_obj2;
22195b482a8SLen Brown
22295b482a8SLen Brown ACPI_FUNCTION_TRACE(ex_create_region);
22395b482a8SLen Brown
22495b482a8SLen Brown /* Get the Namespace Node */
22595b482a8SLen Brown
22695b482a8SLen Brown node = walk_state->op->common.node;
22795b482a8SLen Brown
22895b482a8SLen Brown /*
22995b482a8SLen Brown * If the region object is already attached to this node,
23095b482a8SLen Brown * just return
23195b482a8SLen Brown */
23295b482a8SLen Brown if (acpi_ns_get_attached_object(node)) {
23395b482a8SLen Brown return_ACPI_STATUS(AE_OK);
23495b482a8SLen Brown }
23595b482a8SLen Brown
23695b482a8SLen Brown /*
23795b482a8SLen Brown * Space ID must be one of the predefined IDs, or in the user-defined
23895b482a8SLen Brown * range
23995b482a8SLen Brown */
240ec463666SBob Moore if (!acpi_is_valid_space_id(space_id)) {
241ec463666SBob Moore /*
242ec463666SBob Moore * Print an error message, but continue. We don't want to abort
243ec463666SBob Moore * a table load for this exception. Instead, if the region is
244ec463666SBob Moore * actually used at runtime, abort the executing method.
245ec463666SBob Moore */
246ec463666SBob Moore ACPI_ERROR((AE_INFO,
247ec463666SBob Moore "Invalid/unknown Address Space ID: 0x%2.2X",
248ec463666SBob Moore space_id));
24995b482a8SLen Brown }
25095b482a8SLen Brown
251f6a22b0bSBob Moore ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Region Type - %s (0x%X)\n",
252ec463666SBob Moore acpi_ut_get_region_name(space_id), space_id));
25395b482a8SLen Brown
25495b482a8SLen Brown /* Create the region descriptor */
25595b482a8SLen Brown
25695b482a8SLen Brown obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
25795b482a8SLen Brown if (!obj_desc) {
25895b482a8SLen Brown status = AE_NO_MEMORY;
25995b482a8SLen Brown goto cleanup;
26095b482a8SLen Brown }
26195b482a8SLen Brown
26295b482a8SLen Brown /*
26395b482a8SLen Brown * Remember location in AML stream of address & length
26495b482a8SLen Brown * operands since they need to be evaluated at run time.
26595b482a8SLen Brown */
266849c2571SLv Zheng region_obj2 = acpi_ns_get_secondary_object(obj_desc);
26795b482a8SLen Brown region_obj2->extra.aml_start = aml_start;
26895b482a8SLen Brown region_obj2->extra.aml_length = aml_length;
269849c2571SLv Zheng region_obj2->extra.method_REG = NULL;
2708931d9eaSLin Ming if (walk_state->scope_info) {
2718931d9eaSLin Ming region_obj2->extra.scope_node =
2728931d9eaSLin Ming walk_state->scope_info->scope.node;
2738931d9eaSLin Ming } else {
2748931d9eaSLin Ming region_obj2->extra.scope_node = node;
2758931d9eaSLin Ming }
27695b482a8SLen Brown
27795b482a8SLen Brown /* Init the region from the operands */
27895b482a8SLen Brown
279ec463666SBob Moore obj_desc->region.space_id = space_id;
28095b482a8SLen Brown obj_desc->region.address = 0;
28195b482a8SLen Brown obj_desc->region.length = 0;
282ca25f92bSJessica Clarke obj_desc->region.pointer = NULL;
28395b482a8SLen Brown obj_desc->region.node = node;
284849c2571SLv Zheng obj_desc->region.handler = NULL;
285849c2571SLv Zheng obj_desc->common.flags &=
286efaed9beSLv Zheng ~(AOPOBJ_SETUP_COMPLETE | AOPOBJ_REG_CONNECTED |
287efaed9beSLv Zheng AOPOBJ_OBJECT_INITIALIZED);
28895b482a8SLen Brown
28995b482a8SLen Brown /* Install the new region object in the parent Node */
29095b482a8SLen Brown
29195b482a8SLen Brown status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION);
29295b482a8SLen Brown
29395b482a8SLen Brown cleanup:
29495b482a8SLen Brown
29595b482a8SLen Brown /* Remove local reference to the object */
29695b482a8SLen Brown
29795b482a8SLen Brown acpi_ut_remove_reference(obj_desc);
29895b482a8SLen Brown return_ACPI_STATUS(status);
29995b482a8SLen Brown }
30095b482a8SLen Brown
30195b482a8SLen Brown /*******************************************************************************
30295b482a8SLen Brown *
30395b482a8SLen Brown * FUNCTION: acpi_ex_create_processor
30495b482a8SLen Brown *
30595b482a8SLen Brown * PARAMETERS: walk_state - Current state
30695b482a8SLen Brown *
30795b482a8SLen Brown * RETURN: Status
30895b482a8SLen Brown *
30995b482a8SLen Brown * DESCRIPTION: Create a new processor object and populate the fields
31095b482a8SLen Brown *
311ba494beeSBob Moore * Processor (Name[0], cpu_ID[1], pblock_addr[2], pblock_length[3])
31295b482a8SLen Brown *
31395b482a8SLen Brown ******************************************************************************/
31495b482a8SLen Brown
acpi_ex_create_processor(struct acpi_walk_state * walk_state)31595b482a8SLen Brown acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state)
31695b482a8SLen Brown {
31795b482a8SLen Brown union acpi_operand_object **operand = &walk_state->operands[0];
31895b482a8SLen Brown union acpi_operand_object *obj_desc;
31995b482a8SLen Brown acpi_status status;
32095b482a8SLen Brown
32195b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ex_create_processor, walk_state);
32295b482a8SLen Brown
32395b482a8SLen Brown /* Create the processor object */
32495b482a8SLen Brown
32595b482a8SLen Brown obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PROCESSOR);
32695b482a8SLen Brown if (!obj_desc) {
32795b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY);
32895b482a8SLen Brown }
32995b482a8SLen Brown
33095b482a8SLen Brown /* Initialize the processor object from the operands */
33195b482a8SLen Brown
33295b482a8SLen Brown obj_desc->processor.proc_id = (u8) operand[1]->integer.value;
33395b482a8SLen Brown obj_desc->processor.length = (u8) operand[3]->integer.value;
33495b482a8SLen Brown obj_desc->processor.address =
33595b482a8SLen Brown (acpi_io_address)operand[2]->integer.value;
33695b482a8SLen Brown
33795b482a8SLen Brown /* Install the processor object in the parent Node */
33895b482a8SLen Brown
33995b482a8SLen Brown status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
34095b482a8SLen Brown obj_desc, ACPI_TYPE_PROCESSOR);
34195b482a8SLen Brown
34295b482a8SLen Brown /* Remove local reference to the object */
34395b482a8SLen Brown
34495b482a8SLen Brown acpi_ut_remove_reference(obj_desc);
34595b482a8SLen Brown return_ACPI_STATUS(status);
34695b482a8SLen Brown }
34795b482a8SLen Brown
34895b482a8SLen Brown /*******************************************************************************
34995b482a8SLen Brown *
35095b482a8SLen Brown * FUNCTION: acpi_ex_create_power_resource
35195b482a8SLen Brown *
35295b482a8SLen Brown * PARAMETERS: walk_state - Current state
35395b482a8SLen Brown *
35495b482a8SLen Brown * RETURN: Status
35595b482a8SLen Brown *
35695b482a8SLen Brown * DESCRIPTION: Create a new power_resource object and populate the fields
35795b482a8SLen Brown *
35895b482a8SLen Brown * power_resource (Name[0], system_level[1], resource_order[2])
35995b482a8SLen Brown *
36095b482a8SLen Brown ******************************************************************************/
36195b482a8SLen Brown
acpi_ex_create_power_resource(struct acpi_walk_state * walk_state)36295b482a8SLen Brown acpi_status acpi_ex_create_power_resource(struct acpi_walk_state *walk_state)
36395b482a8SLen Brown {
36495b482a8SLen Brown union acpi_operand_object **operand = &walk_state->operands[0];
36595b482a8SLen Brown acpi_status status;
36695b482a8SLen Brown union acpi_operand_object *obj_desc;
36795b482a8SLen Brown
36895b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ex_create_power_resource, walk_state);
36995b482a8SLen Brown
37095b482a8SLen Brown /* Create the power resource object */
37195b482a8SLen Brown
37295b482a8SLen Brown obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_POWER);
37395b482a8SLen Brown if (!obj_desc) {
37495b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY);
37595b482a8SLen Brown }
37695b482a8SLen Brown
37795b482a8SLen Brown /* Initialize the power object from the operands */
37895b482a8SLen Brown
37995b482a8SLen Brown obj_desc->power_resource.system_level = (u8) operand[1]->integer.value;
38095b482a8SLen Brown obj_desc->power_resource.resource_order =
38195b482a8SLen Brown (u16) operand[2]->integer.value;
38295b482a8SLen Brown
38395b482a8SLen Brown /* Install the power resource object in the parent Node */
38495b482a8SLen Brown
38595b482a8SLen Brown status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
38695b482a8SLen Brown obj_desc, ACPI_TYPE_POWER);
38795b482a8SLen Brown
38895b482a8SLen Brown /* Remove local reference to the object */
38995b482a8SLen Brown
39095b482a8SLen Brown acpi_ut_remove_reference(obj_desc);
39195b482a8SLen Brown return_ACPI_STATUS(status);
39295b482a8SLen Brown }
39395b482a8SLen Brown
39495b482a8SLen Brown /*******************************************************************************
39595b482a8SLen Brown *
39695b482a8SLen Brown * FUNCTION: acpi_ex_create_method
39795b482a8SLen Brown *
39895b482a8SLen Brown * PARAMETERS: aml_start - First byte of the method's AML
39995b482a8SLen Brown * aml_length - AML byte count for this method
40095b482a8SLen Brown * walk_state - Current state
40195b482a8SLen Brown *
40295b482a8SLen Brown * RETURN: Status
40395b482a8SLen Brown *
40495b482a8SLen Brown * DESCRIPTION: Create a new method object
40595b482a8SLen Brown *
40695b482a8SLen Brown ******************************************************************************/
40795b482a8SLen Brown
40895b482a8SLen Brown acpi_status
acpi_ex_create_method(u8 * aml_start,u32 aml_length,struct acpi_walk_state * walk_state)40995b482a8SLen Brown acpi_ex_create_method(u8 * aml_start,
41095b482a8SLen Brown u32 aml_length, struct acpi_walk_state *walk_state)
41195b482a8SLen Brown {
41295b482a8SLen Brown union acpi_operand_object **operand = &walk_state->operands[0];
41395b482a8SLen Brown union acpi_operand_object *obj_desc;
41495b482a8SLen Brown acpi_status status;
41595b482a8SLen Brown u8 method_flags;
41695b482a8SLen Brown
41795b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ex_create_method, walk_state);
41895b482a8SLen Brown
41995b482a8SLen Brown /* Create a new method object */
42095b482a8SLen Brown
42195b482a8SLen Brown obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
42295b482a8SLen Brown if (!obj_desc) {
42395b482a8SLen Brown status = AE_NO_MEMORY;
42495b482a8SLen Brown goto exit;
42595b482a8SLen Brown }
42695b482a8SLen Brown
42795b482a8SLen Brown /* Save the method's AML pointer and length */
42895b482a8SLen Brown
42995b482a8SLen Brown obj_desc->method.aml_start = aml_start;
43095b482a8SLen Brown obj_desc->method.aml_length = aml_length;
43107b9c912SLv Zheng obj_desc->method.node = operand[0];
43295b482a8SLen Brown
43395b482a8SLen Brown /*
43426294842SLin Ming * Disassemble the method flags. Split off the arg_count, Serialized
43526294842SLin Ming * flag, and sync_level for efficiency.
43695b482a8SLen Brown */
43795b482a8SLen Brown method_flags = (u8)operand[1]->integer.value;
4381fad8738SBob Moore obj_desc->method.param_count = (u8)
4391fad8738SBob Moore (method_flags & AML_METHOD_ARG_COUNT);
44095b482a8SLen Brown
44195b482a8SLen Brown /*
44295b482a8SLen Brown * Get the sync_level. If method is serialized, a mutex will be
44395b482a8SLen Brown * created for this method when it is parsed.
44495b482a8SLen Brown */
44595b482a8SLen Brown if (method_flags & AML_METHOD_SERIALIZED) {
44626294842SLin Ming obj_desc->method.info_flags = ACPI_METHOD_SERIALIZED;
44726294842SLin Ming
44895b482a8SLen Brown /*
44995b482a8SLen Brown * ACPI 1.0: sync_level = 0
45095b482a8SLen Brown * ACPI 2.0: sync_level = sync_level in method declaration
45195b482a8SLen Brown */
45295b482a8SLen Brown obj_desc->method.sync_level = (u8)
453b2f7ddcfSLin Ming ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4);
45495b482a8SLen Brown }
45595b482a8SLen Brown
45695b482a8SLen Brown /* Attach the new object to the method Node */
45795b482a8SLen Brown
45895b482a8SLen Brown status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
45995b482a8SLen Brown obj_desc, ACPI_TYPE_METHOD);
46095b482a8SLen Brown
46195b482a8SLen Brown /* Remove local reference to the object */
46295b482a8SLen Brown
46395b482a8SLen Brown acpi_ut_remove_reference(obj_desc);
46495b482a8SLen Brown
46595b482a8SLen Brown exit:
46695b482a8SLen Brown /* Remove a reference to the operand */
46795b482a8SLen Brown
46895b482a8SLen Brown acpi_ut_remove_reference(operand[1]);
46995b482a8SLen Brown return_ACPI_STATUS(status);
47095b482a8SLen Brown }
471