Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: excreate - Named object creation
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acinterp.h"
0013 #include "amlcode.h"
0014 #include "acnamesp.h"
0015 
0016 #define _COMPONENT          ACPI_EXECUTER
0017 ACPI_MODULE_NAME("excreate")
0018 /*******************************************************************************
0019  *
0020  * FUNCTION:    acpi_ex_create_alias
0021  *
0022  * PARAMETERS:  walk_state           - Current state, contains operands
0023  *
0024  * RETURN:      Status
0025  *
0026  * DESCRIPTION: Create a new named alias
0027  *
0028  ******************************************************************************/
0029 acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
0030 {
0031     struct acpi_namespace_node *target_node;
0032     struct acpi_namespace_node *alias_node;
0033     acpi_status status = AE_OK;
0034 
0035     ACPI_FUNCTION_TRACE(ex_create_alias);
0036 
0037     /* Get the source/alias operands (both namespace nodes) */
0038 
0039     alias_node = (struct acpi_namespace_node *)walk_state->operands[0];
0040     target_node = (struct acpi_namespace_node *)walk_state->operands[1];
0041 
0042     if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) ||
0043         (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
0044         /*
0045          * Dereference an existing alias so that we don't create a chain
0046          * of aliases. With this code, we guarantee that an alias is
0047          * always exactly one level of indirection away from the
0048          * actual aliased name.
0049          */
0050         target_node =
0051             ACPI_CAST_PTR(struct acpi_namespace_node,
0052                   target_node->object);
0053     }
0054 
0055     /* Ensure that the target node is valid */
0056 
0057     if (!target_node) {
0058         return_ACPI_STATUS(AE_NULL_OBJECT);
0059     }
0060 
0061     /* Construct the alias object (a namespace node) */
0062 
0063     switch (target_node->type) {
0064     case ACPI_TYPE_METHOD:
0065         /*
0066          * Control method aliases need to be differentiated with
0067          * a special type
0068          */
0069         alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
0070         break;
0071 
0072     default:
0073         /*
0074          * All other object types.
0075          *
0076          * The new alias has the type ALIAS and points to the original
0077          * NS node, not the object itself.
0078          */
0079         alias_node->type = ACPI_TYPE_LOCAL_ALIAS;
0080         alias_node->object =
0081             ACPI_CAST_PTR(union acpi_operand_object, target_node);
0082         break;
0083     }
0084 
0085     /* Since both operands are Nodes, we don't need to delete them */
0086 
0087     alias_node->object =
0088         ACPI_CAST_PTR(union acpi_operand_object, target_node);
0089     return_ACPI_STATUS(status);
0090 }
0091 
0092 /*******************************************************************************
0093  *
0094  * FUNCTION:    acpi_ex_create_event
0095  *
0096  * PARAMETERS:  walk_state          - Current state
0097  *
0098  * RETURN:      Status
0099  *
0100  * DESCRIPTION: Create a new event object
0101  *
0102  ******************************************************************************/
0103 
0104 acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state)
0105 {
0106     acpi_status status;
0107     union acpi_operand_object *obj_desc;
0108 
0109     ACPI_FUNCTION_TRACE(ex_create_event);
0110 
0111     obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_EVENT);
0112     if (!obj_desc) {
0113         status = AE_NO_MEMORY;
0114         goto cleanup;
0115     }
0116 
0117     /*
0118      * Create the actual OS semaphore, with zero initial units -- meaning
0119      * that the event is created in an unsignalled state
0120      */
0121     status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0,
0122                       &obj_desc->event.os_semaphore);
0123     if (ACPI_FAILURE(status)) {
0124         goto cleanup;
0125     }
0126 
0127     /* Attach object to the Node */
0128 
0129     status = acpi_ns_attach_object((struct acpi_namespace_node *)
0130                        walk_state->operands[0], obj_desc,
0131                        ACPI_TYPE_EVENT);
0132 
0133 cleanup:
0134     /*
0135      * Remove local reference to the object (on error, will cause deletion
0136      * of both object and semaphore if present.)
0137      */
0138     acpi_ut_remove_reference(obj_desc);
0139     return_ACPI_STATUS(status);
0140 }
0141 
0142 /*******************************************************************************
0143  *
0144  * FUNCTION:    acpi_ex_create_mutex
0145  *
0146  * PARAMETERS:  walk_state          - Current state
0147  *
0148  * RETURN:      Status
0149  *
0150  * DESCRIPTION: Create a new mutex object
0151  *
0152  *              Mutex (Name[0], sync_level[1])
0153  *
0154  ******************************************************************************/
0155 
0156 acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)
0157 {
0158     acpi_status status = AE_OK;
0159     union acpi_operand_object *obj_desc;
0160 
0161     ACPI_FUNCTION_TRACE_PTR(ex_create_mutex, ACPI_WALK_OPERANDS);
0162 
0163     /* Create the new mutex object */
0164 
0165     obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_MUTEX);
0166     if (!obj_desc) {
0167         status = AE_NO_MEMORY;
0168         goto cleanup;
0169     }
0170 
0171     /* Create the actual OS Mutex */
0172 
0173     status = acpi_os_create_mutex(&obj_desc->mutex.os_mutex);
0174     if (ACPI_FAILURE(status)) {
0175         goto cleanup;
0176     }
0177 
0178     /* Init object and attach to NS node */
0179 
0180     obj_desc->mutex.sync_level = (u8)walk_state->operands[1]->integer.value;
0181     obj_desc->mutex.node =
0182         (struct acpi_namespace_node *)walk_state->operands[0];
0183 
0184     status =
0185         acpi_ns_attach_object(obj_desc->mutex.node, obj_desc,
0186                   ACPI_TYPE_MUTEX);
0187 
0188 cleanup:
0189     /*
0190      * Remove local reference to the object (on error, will cause deletion
0191      * of both object and semaphore if present.)
0192      */
0193     acpi_ut_remove_reference(obj_desc);
0194     return_ACPI_STATUS(status);
0195 }
0196 
0197 /*******************************************************************************
0198  *
0199  * FUNCTION:    acpi_ex_create_region
0200  *
0201  * PARAMETERS:  aml_start           - Pointer to the region declaration AML
0202  *              aml_length          - Max length of the declaration AML
0203  *              space_id            - Address space ID for the region
0204  *              walk_state          - Current state
0205  *
0206  * RETURN:      Status
0207  *
0208  * DESCRIPTION: Create a new operation region object
0209  *
0210  ******************************************************************************/
0211 
0212 acpi_status
0213 acpi_ex_create_region(u8 * aml_start,
0214               u32 aml_length,
0215               u8 space_id, struct acpi_walk_state *walk_state)
0216 {
0217     acpi_status status;
0218     union acpi_operand_object *obj_desc;
0219     struct acpi_namespace_node *node;
0220     union acpi_operand_object *region_obj2;
0221 
0222     ACPI_FUNCTION_TRACE(ex_create_region);
0223 
0224     /* Get the Namespace Node */
0225 
0226     node = walk_state->op->common.node;
0227 
0228     /*
0229      * If the region object is already attached to this node,
0230      * just return
0231      */
0232     if (acpi_ns_get_attached_object(node)) {
0233         return_ACPI_STATUS(AE_OK);
0234     }
0235 
0236     /*
0237      * Space ID must be one of the predefined IDs, or in the user-defined
0238      * range
0239      */
0240     if (!acpi_is_valid_space_id(space_id)) {
0241         /*
0242          * Print an error message, but continue. We don't want to abort
0243          * a table load for this exception. Instead, if the region is
0244          * actually used at runtime, abort the executing method.
0245          */
0246         ACPI_ERROR((AE_INFO,
0247                 "Invalid/unknown Address Space ID: 0x%2.2X",
0248                 space_id));
0249     }
0250 
0251     ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Region Type - %s (0x%X)\n",
0252               acpi_ut_get_region_name(space_id), space_id));
0253 
0254     /* Create the region descriptor */
0255 
0256     obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
0257     if (!obj_desc) {
0258         status = AE_NO_MEMORY;
0259         goto cleanup;
0260     }
0261 
0262     /*
0263      * Remember location in AML stream of address & length
0264      * operands since they need to be evaluated at run time.
0265      */
0266     region_obj2 = acpi_ns_get_secondary_object(obj_desc);
0267     region_obj2->extra.aml_start = aml_start;
0268     region_obj2->extra.aml_length = aml_length;
0269     region_obj2->extra.method_REG = NULL;
0270     if (walk_state->scope_info) {
0271         region_obj2->extra.scope_node =
0272             walk_state->scope_info->scope.node;
0273     } else {
0274         region_obj2->extra.scope_node = node;
0275     }
0276 
0277     /* Init the region from the operands */
0278 
0279     obj_desc->region.space_id = space_id;
0280     obj_desc->region.address = 0;
0281     obj_desc->region.length = 0;
0282     obj_desc->region.pointer = NULL;
0283     obj_desc->region.node = node;
0284     obj_desc->region.handler = NULL;
0285     obj_desc->common.flags &=
0286         ~(AOPOBJ_SETUP_COMPLETE | AOPOBJ_REG_CONNECTED |
0287           AOPOBJ_OBJECT_INITIALIZED);
0288 
0289     /* Install the new region object in the parent Node */
0290 
0291     status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION);
0292 
0293 cleanup:
0294 
0295     /* Remove local reference to the object */
0296 
0297     acpi_ut_remove_reference(obj_desc);
0298     return_ACPI_STATUS(status);
0299 }
0300 
0301 /*******************************************************************************
0302  *
0303  * FUNCTION:    acpi_ex_create_processor
0304  *
0305  * PARAMETERS:  walk_state          - Current state
0306  *
0307  * RETURN:      Status
0308  *
0309  * DESCRIPTION: Create a new processor object and populate the fields
0310  *
0311  *              Processor (Name[0], cpu_ID[1], pblock_addr[2], pblock_length[3])
0312  *
0313  ******************************************************************************/
0314 
0315 acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state)
0316 {
0317     union acpi_operand_object **operand = &walk_state->operands[0];
0318     union acpi_operand_object *obj_desc;
0319     acpi_status status;
0320 
0321     ACPI_FUNCTION_TRACE_PTR(ex_create_processor, walk_state);
0322 
0323     /* Create the processor object */
0324 
0325     obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PROCESSOR);
0326     if (!obj_desc) {
0327         return_ACPI_STATUS(AE_NO_MEMORY);
0328     }
0329 
0330     /* Initialize the processor object from the operands */
0331 
0332     obj_desc->processor.proc_id = (u8) operand[1]->integer.value;
0333     obj_desc->processor.length = (u8) operand[3]->integer.value;
0334     obj_desc->processor.address =
0335         (acpi_io_address)operand[2]->integer.value;
0336 
0337     /* Install the processor object in the parent Node */
0338 
0339     status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
0340                        obj_desc, ACPI_TYPE_PROCESSOR);
0341 
0342     /* Remove local reference to the object */
0343 
0344     acpi_ut_remove_reference(obj_desc);
0345     return_ACPI_STATUS(status);
0346 }
0347 
0348 /*******************************************************************************
0349  *
0350  * FUNCTION:    acpi_ex_create_power_resource
0351  *
0352  * PARAMETERS:  walk_state          - Current state
0353  *
0354  * RETURN:      Status
0355  *
0356  * DESCRIPTION: Create a new power_resource object and populate the fields
0357  *
0358  *              power_resource (Name[0], system_level[1], resource_order[2])
0359  *
0360  ******************************************************************************/
0361 
0362 acpi_status acpi_ex_create_power_resource(struct acpi_walk_state *walk_state)
0363 {
0364     union acpi_operand_object **operand = &walk_state->operands[0];
0365     acpi_status status;
0366     union acpi_operand_object *obj_desc;
0367 
0368     ACPI_FUNCTION_TRACE_PTR(ex_create_power_resource, walk_state);
0369 
0370     /* Create the power resource object */
0371 
0372     obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_POWER);
0373     if (!obj_desc) {
0374         return_ACPI_STATUS(AE_NO_MEMORY);
0375     }
0376 
0377     /* Initialize the power object from the operands */
0378 
0379     obj_desc->power_resource.system_level = (u8) operand[1]->integer.value;
0380     obj_desc->power_resource.resource_order =
0381         (u16) operand[2]->integer.value;
0382 
0383     /* Install the  power resource object in the parent Node */
0384 
0385     status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
0386                        obj_desc, ACPI_TYPE_POWER);
0387 
0388     /* Remove local reference to the object */
0389 
0390     acpi_ut_remove_reference(obj_desc);
0391     return_ACPI_STATUS(status);
0392 }
0393 
0394 /*******************************************************************************
0395  *
0396  * FUNCTION:    acpi_ex_create_method
0397  *
0398  * PARAMETERS:  aml_start       - First byte of the method's AML
0399  *              aml_length      - AML byte count for this method
0400  *              walk_state      - Current state
0401  *
0402  * RETURN:      Status
0403  *
0404  * DESCRIPTION: Create a new method object
0405  *
0406  ******************************************************************************/
0407 
0408 acpi_status
0409 acpi_ex_create_method(u8 * aml_start,
0410               u32 aml_length, struct acpi_walk_state *walk_state)
0411 {
0412     union acpi_operand_object **operand = &walk_state->operands[0];
0413     union acpi_operand_object *obj_desc;
0414     acpi_status status;
0415     u8 method_flags;
0416 
0417     ACPI_FUNCTION_TRACE_PTR(ex_create_method, walk_state);
0418 
0419     /* Create a new method object */
0420 
0421     obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
0422     if (!obj_desc) {
0423         status = AE_NO_MEMORY;
0424         goto exit;
0425     }
0426 
0427     /* Save the method's AML pointer and length  */
0428 
0429     obj_desc->method.aml_start = aml_start;
0430     obj_desc->method.aml_length = aml_length;
0431     obj_desc->method.node = operand[0];
0432 
0433     /*
0434      * Disassemble the method flags. Split off the arg_count, Serialized
0435      * flag, and sync_level for efficiency.
0436      */
0437     method_flags = (u8)operand[1]->integer.value;
0438     obj_desc->method.param_count = (u8)
0439         (method_flags & AML_METHOD_ARG_COUNT);
0440 
0441     /*
0442      * Get the sync_level. If method is serialized, a mutex will be
0443      * created for this method when it is parsed.
0444      */
0445     if (method_flags & AML_METHOD_SERIALIZED) {
0446         obj_desc->method.info_flags = ACPI_METHOD_SERIALIZED;
0447 
0448         /*
0449          * ACPI 1.0: sync_level = 0
0450          * ACPI 2.0: sync_level = sync_level in method declaration
0451          */
0452         obj_desc->method.sync_level = (u8)
0453             ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4);
0454     }
0455 
0456     /* Attach the new object to the method Node */
0457 
0458     status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
0459                        obj_desc, ACPI_TYPE_METHOD);
0460 
0461     /* Remove local reference to the object */
0462 
0463     acpi_ut_remove_reference(obj_desc);
0464 
0465 exit:
0466     /* Remove a reference to the operand */
0467 
0468     acpi_ut_remove_reference(operand[1]);
0469     return_ACPI_STATUS(status);
0470 }