Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: exstore - AML Interpreter object store support
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acdispat.h"
0013 #include "acinterp.h"
0014 #include "amlcode.h"
0015 #include "acnamesp.h"
0016 
0017 #define _COMPONENT          ACPI_EXECUTER
0018 ACPI_MODULE_NAME("exstore")
0019 
0020 /* Local prototypes */
0021 static acpi_status
0022 acpi_ex_store_object_to_index(union acpi_operand_object *val_desc,
0023                   union acpi_operand_object *dest_desc,
0024                   struct acpi_walk_state *walk_state);
0025 
0026 static acpi_status
0027 acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc,
0028                  struct acpi_namespace_node *node,
0029                  struct acpi_walk_state *walk_state);
0030 
0031 /*******************************************************************************
0032  *
0033  * FUNCTION:    acpi_ex_store
0034  *
0035  * PARAMETERS:  *source_desc        - Value to be stored
0036  *              *dest_desc          - Where to store it. Must be an NS node
0037  *                                    or union acpi_operand_object of type
0038  *                                    Reference;
0039  *              walk_state          - Current walk state
0040  *
0041  * RETURN:      Status
0042  *
0043  * DESCRIPTION: Store the value described by source_desc into the location
0044  *              described by dest_desc. Called by various interpreter
0045  *              functions to store the result of an operation into
0046  *              the destination operand -- not just simply the actual "Store"
0047  *              ASL operator.
0048  *
0049  ******************************************************************************/
0050 
0051 acpi_status
0052 acpi_ex_store(union acpi_operand_object *source_desc,
0053           union acpi_operand_object *dest_desc,
0054           struct acpi_walk_state *walk_state)
0055 {
0056     acpi_status status = AE_OK;
0057     union acpi_operand_object *ref_desc = dest_desc;
0058 
0059     ACPI_FUNCTION_TRACE_PTR(ex_store, dest_desc);
0060 
0061     /* Validate parameters */
0062 
0063     if (!source_desc || !dest_desc) {
0064         ACPI_ERROR((AE_INFO, "Null parameter"));
0065         return_ACPI_STATUS(AE_AML_NO_OPERAND);
0066     }
0067 
0068     /* dest_desc can be either a namespace node or an ACPI object */
0069 
0070     if (ACPI_GET_DESCRIPTOR_TYPE(dest_desc) == ACPI_DESC_TYPE_NAMED) {
0071         /*
0072          * Dest is a namespace node,
0073          * Storing an object into a Named node.
0074          */
0075         status = acpi_ex_store_object_to_node(source_desc,
0076                               (struct
0077                                acpi_namespace_node *)
0078                               dest_desc, walk_state,
0079                               ACPI_IMPLICIT_CONVERSION);
0080 
0081         return_ACPI_STATUS(status);
0082     }
0083 
0084     /* Destination object must be a Reference or a Constant object */
0085 
0086     switch (dest_desc->common.type) {
0087     case ACPI_TYPE_LOCAL_REFERENCE:
0088 
0089         break;
0090 
0091     case ACPI_TYPE_INTEGER:
0092 
0093         /* Allow stores to Constants -- a Noop as per ACPI spec */
0094 
0095         if (dest_desc->common.flags & AOPOBJ_AML_CONSTANT) {
0096             return_ACPI_STATUS(AE_OK);
0097         }
0098 
0099         ACPI_FALLTHROUGH;
0100 
0101     default:
0102 
0103         /* Destination is not a Reference object */
0104 
0105         ACPI_ERROR((AE_INFO,
0106                 "Target is not a Reference or Constant object - [%s] %p",
0107                 acpi_ut_get_object_type_name(dest_desc),
0108                 dest_desc));
0109 
0110         return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
0111     }
0112 
0113     /*
0114      * Examine the Reference class. These cases are handled:
0115      *
0116      * 1) Store to Name (Change the object associated with a name)
0117      * 2) Store to an indexed area of a Buffer or Package
0118      * 3) Store to a Method Local or Arg
0119      * 4) Store to the debug object
0120      */
0121     switch (ref_desc->reference.class) {
0122     case ACPI_REFCLASS_REFOF:
0123 
0124         /* Storing an object into a Name "container" */
0125 
0126         status = acpi_ex_store_object_to_node(source_desc,
0127                               ref_desc->reference.
0128                               object, walk_state,
0129                               ACPI_IMPLICIT_CONVERSION);
0130         break;
0131 
0132     case ACPI_REFCLASS_INDEX:
0133 
0134         /* Storing to an Index (pointer into a packager or buffer) */
0135 
0136         status =
0137             acpi_ex_store_object_to_index(source_desc, ref_desc,
0138                           walk_state);
0139         break;
0140 
0141     case ACPI_REFCLASS_LOCAL:
0142     case ACPI_REFCLASS_ARG:
0143 
0144         /* Store to a method local/arg  */
0145 
0146         status =
0147             acpi_ds_store_object_to_local(ref_desc->reference.class,
0148                           ref_desc->reference.value,
0149                           source_desc, walk_state);
0150         break;
0151 
0152     case ACPI_REFCLASS_DEBUG:
0153         /*
0154          * Storing to the Debug object causes the value stored to be
0155          * displayed and otherwise has no effect -- see ACPI Specification
0156          */
0157         ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0158                   "**** Write to Debug Object: Object %p [%s] ****:\n\n",
0159                   source_desc,
0160                   acpi_ut_get_object_type_name(source_desc)));
0161 
0162         ACPI_DEBUG_OBJECT(source_desc, 0, 0);
0163         break;
0164 
0165     default:
0166 
0167         ACPI_ERROR((AE_INFO, "Unknown Reference Class 0x%2.2X",
0168                 ref_desc->reference.class));
0169         ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_INFO);
0170 
0171         status = AE_AML_INTERNAL;
0172         break;
0173     }
0174 
0175     return_ACPI_STATUS(status);
0176 }
0177 
0178 /*******************************************************************************
0179  *
0180  * FUNCTION:    acpi_ex_store_object_to_index
0181  *
0182  * PARAMETERS:  *source_desc            - Value to be stored
0183  *              *dest_desc              - Named object to receive the value
0184  *              walk_state              - Current walk state
0185  *
0186  * RETURN:      Status
0187  *
0188  * DESCRIPTION: Store the object to indexed Buffer or Package element
0189  *
0190  ******************************************************************************/
0191 
0192 static acpi_status
0193 acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
0194                   union acpi_operand_object *index_desc,
0195                   struct acpi_walk_state *walk_state)
0196 {
0197     acpi_status status = AE_OK;
0198     union acpi_operand_object *obj_desc;
0199     union acpi_operand_object *new_desc;
0200     u8 value = 0;
0201     u32 i;
0202 
0203     ACPI_FUNCTION_TRACE(ex_store_object_to_index);
0204 
0205     /*
0206      * Destination must be a reference pointer, and
0207      * must point to either a buffer or a package
0208      */
0209     switch (index_desc->reference.target_type) {
0210     case ACPI_TYPE_PACKAGE:
0211         /*
0212          * Storing to a package element. Copy the object and replace
0213          * any existing object with the new object. No implicit
0214          * conversion is performed.
0215          *
0216          * The object at *(index_desc->Reference.Where) is the
0217          * element within the package that is to be modified.
0218          * The parent package object is at index_desc->Reference.Object
0219          */
0220         obj_desc = *(index_desc->reference.where);
0221 
0222         if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE &&
0223             source_desc->reference.class == ACPI_REFCLASS_TABLE) {
0224 
0225             /* This is a DDBHandle, just add a reference to it */
0226 
0227             acpi_ut_add_reference(source_desc);
0228             new_desc = source_desc;
0229         } else {
0230             /* Normal object, copy it */
0231 
0232             status =
0233                 acpi_ut_copy_iobject_to_iobject(source_desc,
0234                                 &new_desc,
0235                                 walk_state);
0236             if (ACPI_FAILURE(status)) {
0237                 return_ACPI_STATUS(status);
0238             }
0239         }
0240 
0241         if (obj_desc) {
0242 
0243             /* Decrement reference count by the ref count of the parent package */
0244 
0245             for (i = 0; i < ((union acpi_operand_object *)
0246                      index_desc->reference.object)->common.
0247                  reference_count; i++) {
0248                 acpi_ut_remove_reference(obj_desc);
0249             }
0250         }
0251 
0252         *(index_desc->reference.where) = new_desc;
0253 
0254         /* Increment ref count by the ref count of the parent package-1 */
0255 
0256         for (i = 1; i < ((union acpi_operand_object *)
0257                  index_desc->reference.object)->common.
0258              reference_count; i++) {
0259             acpi_ut_add_reference(new_desc);
0260         }
0261 
0262         break;
0263 
0264     case ACPI_TYPE_BUFFER_FIELD:
0265         /*
0266          * Store into a Buffer or String (not actually a real buffer_field)
0267          * at a location defined by an Index.
0268          *
0269          * The first 8-bit element of the source object is written to the
0270          * 8-bit Buffer location defined by the Index destination object,
0271          * according to the ACPI 2.0 specification.
0272          */
0273 
0274         /*
0275          * Make sure the target is a Buffer or String. An error should
0276          * not happen here, since the reference_object was constructed
0277          * by the INDEX_OP code.
0278          */
0279         obj_desc = index_desc->reference.object;
0280         if ((obj_desc->common.type != ACPI_TYPE_BUFFER) &&
0281             (obj_desc->common.type != ACPI_TYPE_STRING)) {
0282             return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
0283         }
0284 
0285         /*
0286          * The assignment of the individual elements will be slightly
0287          * different for each source type.
0288          */
0289         switch (source_desc->common.type) {
0290         case ACPI_TYPE_INTEGER:
0291 
0292             /* Use the least-significant byte of the integer */
0293 
0294             value = (u8) (source_desc->integer.value);
0295             break;
0296 
0297         case ACPI_TYPE_BUFFER:
0298         case ACPI_TYPE_STRING:
0299 
0300             /* Note: Takes advantage of common string/buffer fields */
0301 
0302             value = source_desc->buffer.pointer[0];
0303             break;
0304 
0305         default:
0306 
0307             /* All other types are invalid */
0308 
0309             ACPI_ERROR((AE_INFO,
0310                     "Source must be type [Integer/Buffer/String], found [%s]",
0311                     acpi_ut_get_object_type_name(source_desc)));
0312             return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
0313         }
0314 
0315         /* Store the source value into the target buffer byte */
0316 
0317         obj_desc->buffer.pointer[index_desc->reference.value] = value;
0318         break;
0319 
0320     default:
0321         ACPI_ERROR((AE_INFO,
0322                 "Target is not of type [Package/BufferField]"));
0323         status = AE_AML_TARGET_TYPE;
0324         break;
0325     }
0326 
0327     return_ACPI_STATUS(status);
0328 }
0329 
0330 /*******************************************************************************
0331  *
0332  * FUNCTION:    acpi_ex_store_object_to_node
0333  *
0334  * PARAMETERS:  source_desc             - Value to be stored
0335  *              node                    - Named object to receive the value
0336  *              walk_state              - Current walk state
0337  *              implicit_conversion     - Perform implicit conversion (yes/no)
0338  *
0339  * RETURN:      Status
0340  *
0341  * DESCRIPTION: Store the object to the named object.
0342  *
0343  * The assignment of an object to a named object is handled here.
0344  * The value passed in will replace the current value (if any)
0345  * with the input value.
0346  *
0347  * When storing into an object the data is converted to the
0348  * target object type then stored in the object. This means
0349  * that the target object type (for an initialized target) will
0350  * not be changed by a store operation. A copy_object can change
0351  * the target type, however.
0352  *
0353  * The implicit_conversion flag is set to NO/FALSE only when
0354  * storing to an arg_x -- as per the rules of the ACPI spec.
0355  *
0356  * Assumes parameters are already validated.
0357  *
0358  ******************************************************************************/
0359 
0360 acpi_status
0361 acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
0362                  struct acpi_namespace_node *node,
0363                  struct acpi_walk_state *walk_state,
0364                  u8 implicit_conversion)
0365 {
0366     acpi_status status = AE_OK;
0367     union acpi_operand_object *target_desc;
0368     union acpi_operand_object *new_desc;
0369     acpi_object_type target_type;
0370 
0371     ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_node, source_desc);
0372 
0373     /* Get current type of the node, and object attached to Node */
0374 
0375     target_type = acpi_ns_get_type(node);
0376     target_desc = acpi_ns_get_attached_object(node);
0377 
0378     ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p [%s] to node %p [%s]\n",
0379               source_desc,
0380               acpi_ut_get_object_type_name(source_desc), node,
0381               acpi_ut_get_type_name(target_type)));
0382 
0383     /* Only limited target types possible for everything except copy_object */
0384 
0385     if (walk_state->opcode != AML_COPY_OBJECT_OP) {
0386         /*
0387          * Only copy_object allows all object types to be overwritten. For
0388          * target_ref(s), there are restrictions on the object types that
0389          * are allowed.
0390          *
0391          * Allowable operations/typing for Store:
0392          *
0393          * 1) Simple Store
0394          *      Integer     --> Integer (Named/Local/Arg)
0395          *      String      --> String  (Named/Local/Arg)
0396          *      Buffer      --> Buffer  (Named/Local/Arg)
0397          *      Package     --> Package (Named/Local/Arg)
0398          *
0399          * 2) Store with implicit conversion
0400          *      Integer     --> String or Buffer  (Named)
0401          *      String      --> Integer or Buffer (Named)
0402          *      Buffer      --> Integer or String (Named)
0403          */
0404         switch (target_type) {
0405         case ACPI_TYPE_PACKAGE:
0406             /*
0407              * Here, can only store a package to an existing package.
0408              * Storing a package to a Local/Arg is OK, and handled
0409              * elsewhere.
0410              */
0411             if (walk_state->opcode == AML_STORE_OP) {
0412                 if (source_desc->common.type !=
0413                     ACPI_TYPE_PACKAGE) {
0414                     ACPI_ERROR((AE_INFO,
0415                             "Cannot assign type [%s] to [Package] "
0416                             "(source must be type Pkg)",
0417                             acpi_ut_get_object_type_name
0418                             (source_desc)));
0419 
0420                     return_ACPI_STATUS(AE_AML_TARGET_TYPE);
0421                 }
0422                 break;
0423             }
0424 
0425             ACPI_FALLTHROUGH;
0426 
0427         case ACPI_TYPE_DEVICE:
0428         case ACPI_TYPE_EVENT:
0429         case ACPI_TYPE_MUTEX:
0430         case ACPI_TYPE_REGION:
0431         case ACPI_TYPE_POWER:
0432         case ACPI_TYPE_PROCESSOR:
0433         case ACPI_TYPE_THERMAL:
0434 
0435             ACPI_ERROR((AE_INFO,
0436                     "Target must be [Buffer/Integer/String/Reference]"
0437                     ", found [%s] (%4.4s)",
0438                     acpi_ut_get_type_name(node->type),
0439                     node->name.ascii));
0440 
0441             return_ACPI_STATUS(AE_AML_TARGET_TYPE);
0442 
0443         default:
0444             break;
0445         }
0446     }
0447 
0448     /*
0449      * Resolve the source object to an actual value
0450      * (If it is a reference object)
0451      */
0452     status = acpi_ex_resolve_object(&source_desc, target_type, walk_state);
0453     if (ACPI_FAILURE(status)) {
0454         return_ACPI_STATUS(status);
0455     }
0456 
0457     /* Do the actual store operation */
0458 
0459     switch (target_type) {
0460         /*
0461          * The simple data types all support implicit source operand
0462          * conversion before the store.
0463          */
0464     case ACPI_TYPE_INTEGER:
0465     case ACPI_TYPE_STRING:
0466     case ACPI_TYPE_BUFFER:
0467 
0468         if ((walk_state->opcode == AML_COPY_OBJECT_OP) ||
0469             !implicit_conversion) {
0470             /*
0471              * However, copy_object and Stores to arg_x do not perform
0472              * an implicit conversion, as per the ACPI specification.
0473              * A direct store is performed instead.
0474              */
0475             status =
0476                 acpi_ex_store_direct_to_node(source_desc, node,
0477                              walk_state);
0478             break;
0479         }
0480 
0481         /* Store with implicit source operand conversion support */
0482 
0483         status =
0484             acpi_ex_store_object_to_object(source_desc, target_desc,
0485                            &new_desc, walk_state);
0486         if (ACPI_FAILURE(status)) {
0487             return_ACPI_STATUS(status);
0488         }
0489 
0490         if (new_desc != target_desc) {
0491             /*
0492              * Store the new new_desc as the new value of the Name, and set
0493              * the Name's type to that of the value being stored in it.
0494              * source_desc reference count is incremented by attach_object.
0495              *
0496              * Note: This may change the type of the node if an explicit
0497              * store has been performed such that the node/object type
0498              * has been changed.
0499              */
0500             status =
0501                 acpi_ns_attach_object(node, new_desc,
0502                           new_desc->common.type);
0503 
0504             ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0505                       "Store type [%s] into [%s] via Convert/Attach\n",
0506                       acpi_ut_get_object_type_name
0507                       (source_desc),
0508                       acpi_ut_get_object_type_name
0509                       (new_desc)));
0510         }
0511         break;
0512 
0513     case ACPI_TYPE_BUFFER_FIELD:
0514     case ACPI_TYPE_LOCAL_REGION_FIELD:
0515     case ACPI_TYPE_LOCAL_BANK_FIELD:
0516     case ACPI_TYPE_LOCAL_INDEX_FIELD:
0517         /*
0518          * For all fields, always write the source data to the target
0519          * field. Any required implicit source operand conversion is
0520          * performed in the function below as necessary. Note, field
0521          * objects must retain their original type permanently.
0522          */
0523         status = acpi_ex_write_data_to_field(source_desc, target_desc,
0524                              &walk_state->result_obj);
0525         break;
0526 
0527     default:
0528         /*
0529          * copy_object operator: No conversions for all other types.
0530          * Instead, directly store a copy of the source object.
0531          *
0532          * This is the ACPI spec-defined behavior for the copy_object
0533          * operator. (Note, for this default case, all normal
0534          * Store/Target operations exited above with an error).
0535          */
0536         status =
0537             acpi_ex_store_direct_to_node(source_desc, node, walk_state);
0538         break;
0539     }
0540 
0541     return_ACPI_STATUS(status);
0542 }
0543 
0544 /*******************************************************************************
0545  *
0546  * FUNCTION:    acpi_ex_store_direct_to_node
0547  *
0548  * PARAMETERS:  source_desc             - Value to be stored
0549  *              node                    - Named object to receive the value
0550  *              walk_state              - Current walk state
0551  *
0552  * RETURN:      Status
0553  *
0554  * DESCRIPTION: "Store" an object directly to a node. This involves a copy
0555  *              and an attach.
0556  *
0557  ******************************************************************************/
0558 
0559 static acpi_status
0560 acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc,
0561                  struct acpi_namespace_node *node,
0562                  struct acpi_walk_state *walk_state)
0563 {
0564     acpi_status status;
0565     union acpi_operand_object *new_desc;
0566 
0567     ACPI_FUNCTION_TRACE(ex_store_direct_to_node);
0568 
0569     ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0570               "Storing [%s] (%p) directly into node [%s] (%p)"
0571               " with no implicit conversion\n",
0572               acpi_ut_get_object_type_name(source_desc),
0573               source_desc, acpi_ut_get_type_name(node->type),
0574               node));
0575 
0576     /* Copy the source object to a new object */
0577 
0578     status =
0579         acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, walk_state);
0580     if (ACPI_FAILURE(status)) {
0581         return_ACPI_STATUS(status);
0582     }
0583 
0584     /* Attach the new object to the node */
0585 
0586     status = acpi_ns_attach_object(node, new_desc, new_desc->common.type);
0587     acpi_ut_remove_reference(new_desc);
0588     return_ACPI_STATUS(status);
0589 }