Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: exresolv - AML Interpreter object resolution
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "amlcode.h"
0013 #include "acdispat.h"
0014 #include "acinterp.h"
0015 #include "acnamesp.h"
0016 
0017 #define _COMPONENT          ACPI_EXECUTER
0018 ACPI_MODULE_NAME("exresolv")
0019 
0020 /* Local prototypes */
0021 static acpi_status
0022 acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
0023                 struct acpi_walk_state *walk_state);
0024 
0025 /*******************************************************************************
0026  *
0027  * FUNCTION:    acpi_ex_resolve_to_value
0028  *
0029  * PARAMETERS:  **stack_ptr         - Points to entry on obj_stack, which can
0030  *                                    be either an (union acpi_operand_object *)
0031  *                                    or an acpi_handle.
0032  *              walk_state          - Current method state
0033  *
0034  * RETURN:      Status
0035  *
0036  * DESCRIPTION: Convert Reference objects to values
0037  *
0038  ******************************************************************************/
0039 
0040 acpi_status
0041 acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr,
0042              struct acpi_walk_state *walk_state)
0043 {
0044     acpi_status status;
0045 
0046     ACPI_FUNCTION_TRACE_PTR(ex_resolve_to_value, stack_ptr);
0047 
0048     if (!stack_ptr || !*stack_ptr) {
0049         ACPI_ERROR((AE_INFO, "Internal - null pointer"));
0050         return_ACPI_STATUS(AE_AML_NO_OPERAND);
0051     }
0052 
0053     /*
0054      * The entity pointed to by the stack_ptr can be either
0055      * 1) A valid union acpi_operand_object, or
0056      * 2) A struct acpi_namespace_node (named_obj)
0057      */
0058     if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_OPERAND) {
0059         status = acpi_ex_resolve_object_to_value(stack_ptr, walk_state);
0060         if (ACPI_FAILURE(status)) {
0061             return_ACPI_STATUS(status);
0062         }
0063 
0064         if (!*stack_ptr) {
0065             ACPI_ERROR((AE_INFO, "Internal - null pointer"));
0066             return_ACPI_STATUS(AE_AML_NO_OPERAND);
0067         }
0068     }
0069 
0070     /*
0071      * Object on the stack may have changed if acpi_ex_resolve_object_to_value()
0072      * was called (i.e., we can't use an _else_ here.)
0073      */
0074     if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_NAMED) {
0075         status =
0076             acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
0077                           (struct acpi_namespace_node,
0078                            stack_ptr), walk_state);
0079         if (ACPI_FAILURE(status)) {
0080             return_ACPI_STATUS(status);
0081         }
0082     }
0083 
0084     ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr));
0085     return_ACPI_STATUS(AE_OK);
0086 }
0087 
0088 /*******************************************************************************
0089  *
0090  * FUNCTION:    acpi_ex_resolve_object_to_value
0091  *
0092  * PARAMETERS:  stack_ptr       - Pointer to an internal object
0093  *              walk_state      - Current method state
0094  *
0095  * RETURN:      Status
0096  *
0097  * DESCRIPTION: Retrieve the value from an internal object. The Reference type
0098  *              uses the associated AML opcode to determine the value.
0099  *
0100  ******************************************************************************/
0101 
0102 static acpi_status
0103 acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
0104                 struct acpi_walk_state *walk_state)
0105 {
0106     acpi_status status = AE_OK;
0107     union acpi_operand_object *stack_desc;
0108     union acpi_operand_object *obj_desc = NULL;
0109     u8 ref_type;
0110 
0111     ACPI_FUNCTION_TRACE(ex_resolve_object_to_value);
0112 
0113     stack_desc = *stack_ptr;
0114 
0115     /* This is an object of type union acpi_operand_object */
0116 
0117     switch (stack_desc->common.type) {
0118     case ACPI_TYPE_LOCAL_REFERENCE:
0119 
0120         ref_type = stack_desc->reference.class;
0121 
0122         switch (ref_type) {
0123         case ACPI_REFCLASS_LOCAL:
0124         case ACPI_REFCLASS_ARG:
0125             /*
0126              * Get the local from the method's state info
0127              * Note: this increments the local's object reference count
0128              */
0129             status = acpi_ds_method_data_get_value(ref_type,
0130                                    stack_desc->
0131                                    reference.value,
0132                                    walk_state,
0133                                    &obj_desc);
0134             if (ACPI_FAILURE(status)) {
0135                 return_ACPI_STATUS(status);
0136             }
0137 
0138             ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0139                       "[Arg/Local %X] ValueObj is %p\n",
0140                       stack_desc->reference.value,
0141                       obj_desc));
0142 
0143             /*
0144              * Now we can delete the original Reference Object and
0145              * replace it with the resolved value
0146              */
0147             acpi_ut_remove_reference(stack_desc);
0148             *stack_ptr = obj_desc;
0149             break;
0150 
0151         case ACPI_REFCLASS_INDEX:
0152 
0153             switch (stack_desc->reference.target_type) {
0154             case ACPI_TYPE_BUFFER_FIELD:
0155 
0156                 /* Just return - do not dereference */
0157                 break;
0158 
0159             case ACPI_TYPE_PACKAGE:
0160 
0161                 /* If method call or copy_object - do not dereference */
0162 
0163                 if ((walk_state->opcode ==
0164                      AML_INT_METHODCALL_OP)
0165                     || (walk_state->opcode ==
0166                     AML_COPY_OBJECT_OP)) {
0167                     break;
0168                 }
0169 
0170                 /* Otherwise, dereference the package_index to a package element */
0171 
0172                 obj_desc = *stack_desc->reference.where;
0173                 if (obj_desc) {
0174                     /*
0175                      * Valid object descriptor, copy pointer to return value
0176                      * (i.e., dereference the package index)
0177                      * Delete the ref object, increment the returned object
0178                      */
0179                     acpi_ut_add_reference(obj_desc);
0180                     *stack_ptr = obj_desc;
0181                 } else {
0182                     /*
0183                      * A NULL object descriptor means an uninitialized element of
0184                      * the package, can't dereference it
0185                      */
0186                     ACPI_ERROR((AE_INFO,
0187                             "Attempt to dereference an Index to "
0188                             "NULL package element Idx=%p",
0189                             stack_desc));
0190                     status = AE_AML_UNINITIALIZED_ELEMENT;
0191                 }
0192                 break;
0193 
0194             default:
0195 
0196                 /* Invalid reference object */
0197 
0198                 ACPI_ERROR((AE_INFO,
0199                         "Unknown TargetType 0x%X in Index/Reference object %p",
0200                         stack_desc->reference.target_type,
0201                         stack_desc));
0202                 status = AE_AML_INTERNAL;
0203                 break;
0204             }
0205             break;
0206 
0207         case ACPI_REFCLASS_REFOF:
0208         case ACPI_REFCLASS_DEBUG:
0209         case ACPI_REFCLASS_TABLE:
0210 
0211             /* Just leave the object as-is, do not dereference */
0212 
0213             break;
0214 
0215         case ACPI_REFCLASS_NAME:    /* Reference to a named object */
0216 
0217             /* Dereference the name */
0218 
0219             if ((stack_desc->reference.node->type ==
0220                  ACPI_TYPE_DEVICE)
0221                 || (stack_desc->reference.node->type ==
0222                 ACPI_TYPE_THERMAL)) {
0223 
0224                 /* These node types do not have 'real' subobjects */
0225 
0226                 *stack_ptr = (void *)stack_desc->reference.node;
0227             } else {
0228                 /* Get the object pointed to by the namespace node */
0229 
0230                 *stack_ptr =
0231                     (stack_desc->reference.node)->object;
0232                 acpi_ut_add_reference(*stack_ptr);
0233             }
0234 
0235             acpi_ut_remove_reference(stack_desc);
0236             break;
0237 
0238         default:
0239 
0240             ACPI_ERROR((AE_INFO,
0241                     "Unknown Reference type 0x%X in %p",
0242                     ref_type, stack_desc));
0243             status = AE_AML_INTERNAL;
0244             break;
0245         }
0246         break;
0247 
0248     case ACPI_TYPE_BUFFER:
0249 
0250         status = acpi_ds_get_buffer_arguments(stack_desc);
0251         break;
0252 
0253     case ACPI_TYPE_PACKAGE:
0254 
0255         status = acpi_ds_get_package_arguments(stack_desc);
0256         break;
0257 
0258     case ACPI_TYPE_BUFFER_FIELD:
0259     case ACPI_TYPE_LOCAL_REGION_FIELD:
0260     case ACPI_TYPE_LOCAL_BANK_FIELD:
0261     case ACPI_TYPE_LOCAL_INDEX_FIELD:
0262 
0263         ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0264                   "FieldRead SourceDesc=%p Type=%X\n",
0265                   stack_desc, stack_desc->common.type));
0266 
0267         status =
0268             acpi_ex_read_data_from_field(walk_state, stack_desc,
0269                          &obj_desc);
0270 
0271         /* Remove a reference to the original operand, then override */
0272 
0273         acpi_ut_remove_reference(*stack_ptr);
0274         *stack_ptr = (void *)obj_desc;
0275         break;
0276 
0277     default:
0278 
0279         break;
0280     }
0281 
0282     return_ACPI_STATUS(status);
0283 }
0284 
0285 /*******************************************************************************
0286  *
0287  * FUNCTION:    acpi_ex_resolve_multiple
0288  *
0289  * PARAMETERS:  walk_state          - Current state (contains AML opcode)
0290  *              operand             - Starting point for resolution
0291  *              return_type         - Where the object type is returned
0292  *              return_desc         - Where the resolved object is returned
0293  *
0294  * RETURN:      Status
0295  *
0296  * DESCRIPTION: Return the base object and type. Traverse a reference list if
0297  *              necessary to get to the base object.
0298  *
0299  ******************************************************************************/
0300 
0301 acpi_status
0302 acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
0303              union acpi_operand_object *operand,
0304              acpi_object_type *return_type,
0305              union acpi_operand_object **return_desc)
0306 {
0307     union acpi_operand_object *obj_desc = ACPI_CAST_PTR(void, operand);
0308     struct acpi_namespace_node *node =
0309         ACPI_CAST_PTR(struct acpi_namespace_node, operand);
0310     acpi_object_type type;
0311     acpi_status status;
0312 
0313     ACPI_FUNCTION_TRACE(acpi_ex_resolve_multiple);
0314 
0315     /* Operand can be either a namespace node or an operand descriptor */
0316 
0317     switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
0318     case ACPI_DESC_TYPE_OPERAND:
0319 
0320         type = obj_desc->common.type;
0321         break;
0322 
0323     case ACPI_DESC_TYPE_NAMED:
0324 
0325         type = ((struct acpi_namespace_node *)obj_desc)->type;
0326         obj_desc = acpi_ns_get_attached_object(node);
0327 
0328         /* If we had an Alias node, use the attached object for type info */
0329 
0330         if (type == ACPI_TYPE_LOCAL_ALIAS) {
0331             type = ((struct acpi_namespace_node *)obj_desc)->type;
0332             obj_desc = acpi_ns_get_attached_object((struct
0333                                 acpi_namespace_node
0334                                 *)obj_desc);
0335         }
0336 
0337         switch (type) {
0338         case ACPI_TYPE_DEVICE:
0339         case ACPI_TYPE_THERMAL:
0340 
0341             /* These types have no attached subobject */
0342             break;
0343 
0344         default:
0345 
0346             /* All other types require a subobject */
0347 
0348             if (!obj_desc) {
0349                 ACPI_ERROR((AE_INFO,
0350                         "[%4.4s] Node is unresolved or uninitialized",
0351                         acpi_ut_get_node_name(node)));
0352                 return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE);
0353             }
0354             break;
0355         }
0356         break;
0357 
0358     default:
0359         return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
0360     }
0361 
0362     /* If type is anything other than a reference, we are done */
0363 
0364     if (type != ACPI_TYPE_LOCAL_REFERENCE) {
0365         goto exit;
0366     }
0367 
0368     /*
0369      * For reference objects created via the ref_of, Index, or Load/load_table
0370      * operators, we need to get to the base object (as per the ACPI
0371      * specification of the object_type and size_of operators). This means
0372      * traversing the list of possibly many nested references.
0373      */
0374     while (obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
0375         switch (obj_desc->reference.class) {
0376         case ACPI_REFCLASS_REFOF:
0377         case ACPI_REFCLASS_NAME:
0378 
0379             /* Dereference the reference pointer */
0380 
0381             if (obj_desc->reference.class == ACPI_REFCLASS_REFOF) {
0382                 node = obj_desc->reference.object;
0383             } else {    /* AML_INT_NAMEPATH_OP */
0384 
0385                 node = obj_desc->reference.node;
0386             }
0387 
0388             /* All "References" point to a NS node */
0389 
0390             if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
0391                 ACPI_DESC_TYPE_NAMED) {
0392                 ACPI_ERROR((AE_INFO,
0393                         "Not a namespace node %p [%s]",
0394                         node,
0395                         acpi_ut_get_descriptor_name(node)));
0396                 return_ACPI_STATUS(AE_AML_INTERNAL);
0397             }
0398 
0399             /* Get the attached object */
0400 
0401             obj_desc = acpi_ns_get_attached_object(node);
0402             if (!obj_desc) {
0403 
0404                 /* No object, use the NS node type */
0405 
0406                 type = acpi_ns_get_type(node);
0407                 goto exit;
0408             }
0409 
0410             /* Check for circular references */
0411 
0412             if (obj_desc == operand) {
0413                 return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE);
0414             }
0415             break;
0416 
0417         case ACPI_REFCLASS_INDEX:
0418 
0419             /* Get the type of this reference (index into another object) */
0420 
0421             type = obj_desc->reference.target_type;
0422             if (type != ACPI_TYPE_PACKAGE) {
0423                 goto exit;
0424             }
0425 
0426             /*
0427              * The main object is a package, we want to get the type
0428              * of the individual package element that is referenced by
0429              * the index.
0430              *
0431              * This could of course in turn be another reference object.
0432              */
0433             obj_desc = *(obj_desc->reference.where);
0434             if (!obj_desc) {
0435 
0436                 /* NULL package elements are allowed */
0437 
0438                 type = 0;   /* Uninitialized */
0439                 goto exit;
0440             }
0441             break;
0442 
0443         case ACPI_REFCLASS_TABLE:
0444 
0445             type = ACPI_TYPE_DDB_HANDLE;
0446             goto exit;
0447 
0448         case ACPI_REFCLASS_LOCAL:
0449         case ACPI_REFCLASS_ARG:
0450 
0451             if (return_desc) {
0452                 status =
0453                     acpi_ds_method_data_get_value(obj_desc->
0454                                   reference.
0455                                   class,
0456                                   obj_desc->
0457                                   reference.
0458                                   value,
0459                                   walk_state,
0460                                   &obj_desc);
0461                 if (ACPI_FAILURE(status)) {
0462                     return_ACPI_STATUS(status);
0463                 }
0464                 acpi_ut_remove_reference(obj_desc);
0465             } else {
0466                 status =
0467                     acpi_ds_method_data_get_node(obj_desc->
0468                                  reference.
0469                                  class,
0470                                  obj_desc->
0471                                  reference.
0472                                  value,
0473                                  walk_state,
0474                                  &node);
0475                 if (ACPI_FAILURE(status)) {
0476                     return_ACPI_STATUS(status);
0477                 }
0478 
0479                 obj_desc = acpi_ns_get_attached_object(node);
0480                 if (!obj_desc) {
0481                     type = ACPI_TYPE_ANY;
0482                     goto exit;
0483                 }
0484             }
0485             break;
0486 
0487         case ACPI_REFCLASS_DEBUG:
0488 
0489             /* The Debug Object is of type "DebugObject" */
0490 
0491             type = ACPI_TYPE_DEBUG_OBJECT;
0492             goto exit;
0493 
0494         default:
0495 
0496             ACPI_ERROR((AE_INFO,
0497                     "Unknown Reference Class 0x%2.2X",
0498                     obj_desc->reference.class));
0499             return_ACPI_STATUS(AE_AML_INTERNAL);
0500         }
0501     }
0502 
0503     /*
0504      * Now we are guaranteed to have an object that has not been created
0505      * via the ref_of or Index operators.
0506      */
0507     type = obj_desc->common.type;
0508 
0509 exit:
0510     /* Convert internal types to external types */
0511 
0512     switch (type) {
0513     case ACPI_TYPE_LOCAL_REGION_FIELD:
0514     case ACPI_TYPE_LOCAL_BANK_FIELD:
0515     case ACPI_TYPE_LOCAL_INDEX_FIELD:
0516 
0517         type = ACPI_TYPE_FIELD_UNIT;
0518         break;
0519 
0520     case ACPI_TYPE_LOCAL_SCOPE:
0521 
0522         /* Per ACPI Specification, Scope is untyped */
0523 
0524         type = ACPI_TYPE_ANY;
0525         break;
0526 
0527     default:
0528 
0529         /* No change to Type required */
0530 
0531         break;
0532     }
0533 
0534     *return_type = type;
0535     if (return_desc) {
0536         *return_desc = obj_desc;
0537     }
0538     return_ACPI_STATUS(AE_OK);
0539 }