Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: dsobject - Dispatcher object management routines
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acparser.h"
0013 #include "amlcode.h"
0014 #include "acdispat.h"
0015 #include "acnamesp.h"
0016 #include "acinterp.h"
0017 
0018 #define _COMPONENT          ACPI_DISPATCHER
0019 ACPI_MODULE_NAME("dsobject")
0020 
0021 /*******************************************************************************
0022  *
0023  * FUNCTION:    acpi_ds_build_internal_object
0024  *
0025  * PARAMETERS:  walk_state      - Current walk state
0026  *              op              - Parser object to be translated
0027  *              obj_desc_ptr    - Where the ACPI internal object is returned
0028  *
0029  * RETURN:      Status
0030  *
0031  * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
0032  *              Simple objects are any objects other than a package object!
0033  *
0034  ******************************************************************************/
0035 acpi_status
0036 acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
0037                   union acpi_parse_object *op,
0038                   union acpi_operand_object **obj_desc_ptr)
0039 {
0040     union acpi_operand_object *obj_desc;
0041     acpi_status status;
0042 
0043     ACPI_FUNCTION_TRACE(ds_build_internal_object);
0044 
0045     *obj_desc_ptr = NULL;
0046     if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
0047         /*
0048          * This is a named object reference. If this name was
0049          * previously looked up in the namespace, it was stored in
0050          * this op. Otherwise, go ahead and look it up now
0051          */
0052         if (!op->common.node) {
0053 
0054             /* Check if we are resolving a named reference within a package */
0055 
0056             if ((op->common.parent->common.aml_opcode ==
0057                  AML_PACKAGE_OP)
0058                 || (op->common.parent->common.aml_opcode ==
0059                 AML_VARIABLE_PACKAGE_OP)) {
0060                 /*
0061                  * We won't resolve package elements here, we will do this
0062                  * after all ACPI tables are loaded into the namespace. This
0063                  * behavior supports both forward references to named objects
0064                  * and external references to objects in other tables.
0065                  */
0066                 goto create_new_object;
0067             } else {
0068                 status = acpi_ns_lookup(walk_state->scope_info,
0069                             op->common.value.string,
0070                             ACPI_TYPE_ANY,
0071                             ACPI_IMODE_EXECUTE,
0072                             ACPI_NS_SEARCH_PARENT |
0073                             ACPI_NS_DONT_OPEN_SCOPE,
0074                             NULL,
0075                             ACPI_CAST_INDIRECT_PTR
0076                             (struct
0077                              acpi_namespace_node,
0078                              &(op->common.node)));
0079                 if (ACPI_FAILURE(status)) {
0080                     ACPI_ERROR_NAMESPACE(walk_state->
0081                                  scope_info,
0082                                  op->common.value.
0083                                  string, status);
0084                     return_ACPI_STATUS(status);
0085                 }
0086             }
0087         }
0088     }
0089 
0090 create_new_object:
0091 
0092     /* Create and init a new internal ACPI object */
0093 
0094     obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info
0095                            (op->common.aml_opcode))->
0096                           object_type);
0097     if (!obj_desc) {
0098         return_ACPI_STATUS(AE_NO_MEMORY);
0099     }
0100 
0101     status =
0102         acpi_ds_init_object_from_op(walk_state, op, op->common.aml_opcode,
0103                     &obj_desc);
0104     if (ACPI_FAILURE(status)) {
0105         acpi_ut_remove_reference(obj_desc);
0106         return_ACPI_STATUS(status);
0107     }
0108 
0109     /*
0110      * Handling for unresolved package reference elements.
0111      * These are elements that are namepaths.
0112      */
0113     if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
0114         (op->common.parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP)) {
0115         obj_desc->reference.resolved = TRUE;
0116 
0117         if ((op->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
0118             !obj_desc->reference.node) {
0119             /*
0120              * Name was unresolved above.
0121              * Get the prefix node for later lookup
0122              */
0123             obj_desc->reference.node =
0124                 walk_state->scope_info->scope.node;
0125             obj_desc->reference.aml = op->common.aml;
0126             obj_desc->reference.resolved = FALSE;
0127         }
0128     }
0129 
0130     *obj_desc_ptr = obj_desc;
0131     return_ACPI_STATUS(status);
0132 }
0133 
0134 /*******************************************************************************
0135  *
0136  * FUNCTION:    acpi_ds_build_internal_buffer_obj
0137  *
0138  * PARAMETERS:  walk_state      - Current walk state
0139  *              op              - Parser object to be translated
0140  *              buffer_length   - Length of the buffer
0141  *              obj_desc_ptr    - Where the ACPI internal object is returned
0142  *
0143  * RETURN:      Status
0144  *
0145  * DESCRIPTION: Translate a parser Op package object to the equivalent
0146  *              namespace object
0147  *
0148  ******************************************************************************/
0149 
0150 acpi_status
0151 acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
0152                   union acpi_parse_object *op,
0153                   u32 buffer_length,
0154                   union acpi_operand_object **obj_desc_ptr)
0155 {
0156     union acpi_parse_object *arg;
0157     union acpi_operand_object *obj_desc;
0158     union acpi_parse_object *byte_list;
0159     u32 byte_list_length = 0;
0160 
0161     ACPI_FUNCTION_TRACE(ds_build_internal_buffer_obj);
0162 
0163     /*
0164      * If we are evaluating a Named buffer object "Name (xxxx, Buffer)".
0165      * The buffer object already exists (from the NS node), otherwise it must
0166      * be created.
0167      */
0168     obj_desc = *obj_desc_ptr;
0169     if (!obj_desc) {
0170 
0171         /* Create a new buffer object */
0172 
0173         obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
0174         *obj_desc_ptr = obj_desc;
0175         if (!obj_desc) {
0176             return_ACPI_STATUS(AE_NO_MEMORY);
0177         }
0178     }
0179 
0180     /*
0181      * Second arg is the buffer data (optional) byte_list can be either
0182      * individual bytes or a string initializer. In either case, a
0183      * byte_list appears in the AML.
0184      */
0185     arg = op->common.value.arg; /* skip first arg */
0186 
0187     byte_list = arg->named.next;
0188     if (byte_list) {
0189         if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) {
0190             ACPI_ERROR((AE_INFO,
0191                     "Expecting bytelist, found AML opcode 0x%X in op %p",
0192                     byte_list->common.aml_opcode, byte_list));
0193 
0194             acpi_ut_remove_reference(obj_desc);
0195             return (AE_TYPE);
0196         }
0197 
0198         byte_list_length = (u32) byte_list->common.value.integer;
0199     }
0200 
0201     /*
0202      * The buffer length (number of bytes) will be the larger of:
0203      * 1) The specified buffer length and
0204      * 2) The length of the initializer byte list
0205      */
0206     obj_desc->buffer.length = buffer_length;
0207     if (byte_list_length > buffer_length) {
0208         obj_desc->buffer.length = byte_list_length;
0209     }
0210 
0211     /* Allocate the buffer */
0212 
0213     if (obj_desc->buffer.length == 0) {
0214         obj_desc->buffer.pointer = NULL;
0215         ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0216                   "Buffer defined with zero length in AML, creating\n"));
0217     } else {
0218         obj_desc->buffer.pointer =
0219             ACPI_ALLOCATE_ZEROED(obj_desc->buffer.length);
0220         if (!obj_desc->buffer.pointer) {
0221             acpi_ut_delete_object_desc(obj_desc);
0222             return_ACPI_STATUS(AE_NO_MEMORY);
0223         }
0224 
0225         /* Initialize buffer from the byte_list (if present) */
0226 
0227         if (byte_list) {
0228             memcpy(obj_desc->buffer.pointer, byte_list->named.data,
0229                    byte_list_length);
0230         }
0231     }
0232 
0233     obj_desc->buffer.flags |= AOPOBJ_DATA_VALID;
0234     op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc);
0235     return_ACPI_STATUS(AE_OK);
0236 }
0237 
0238 /*******************************************************************************
0239  *
0240  * FUNCTION:    acpi_ds_create_node
0241  *
0242  * PARAMETERS:  walk_state      - Current walk state
0243  *              node            - NS Node to be initialized
0244  *              op              - Parser object to be translated
0245  *
0246  * RETURN:      Status
0247  *
0248  * DESCRIPTION: Create the object to be associated with a namespace node
0249  *
0250  ******************************************************************************/
0251 
0252 acpi_status
0253 acpi_ds_create_node(struct acpi_walk_state *walk_state,
0254             struct acpi_namespace_node *node,
0255             union acpi_parse_object *op)
0256 {
0257     acpi_status status;
0258     union acpi_operand_object *obj_desc;
0259 
0260     ACPI_FUNCTION_TRACE_PTR(ds_create_node, op);
0261 
0262     /*
0263      * Because of the execution pass through the non-control-method
0264      * parts of the table, we can arrive here twice. Only init
0265      * the named object node the first time through
0266      */
0267     if (acpi_ns_get_attached_object(node)) {
0268         return_ACPI_STATUS(AE_OK);
0269     }
0270 
0271     if (!op->common.value.arg) {
0272 
0273         /* No arguments, there is nothing to do */
0274 
0275         return_ACPI_STATUS(AE_OK);
0276     }
0277 
0278     /* Build an internal object for the argument(s) */
0279 
0280     status =
0281         acpi_ds_build_internal_object(walk_state, op->common.value.arg,
0282                       &obj_desc);
0283     if (ACPI_FAILURE(status)) {
0284         return_ACPI_STATUS(status);
0285     }
0286 
0287     /* Re-type the object according to its argument */
0288 
0289     node->type = obj_desc->common.type;
0290 
0291     /* Attach obj to node */
0292 
0293     status = acpi_ns_attach_object(node, obj_desc, node->type);
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_ds_init_object_from_op
0304  *
0305  * PARAMETERS:  walk_state      - Current walk state
0306  *              op              - Parser op used to init the internal object
0307  *              opcode          - AML opcode associated with the object
0308  *              ret_obj_desc    - Namespace object to be initialized
0309  *
0310  * RETURN:      Status
0311  *
0312  * DESCRIPTION: Initialize a namespace object from a parser Op and its
0313  *              associated arguments. The namespace object is a more compact
0314  *              representation of the Op and its arguments.
0315  *
0316  ******************************************************************************/
0317 
0318 acpi_status
0319 acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
0320                 union acpi_parse_object *op,
0321                 u16 opcode,
0322                 union acpi_operand_object **ret_obj_desc)
0323 {
0324     const struct acpi_opcode_info *op_info;
0325     union acpi_operand_object *obj_desc;
0326     acpi_status status = AE_OK;
0327 
0328     ACPI_FUNCTION_TRACE(ds_init_object_from_op);
0329 
0330     obj_desc = *ret_obj_desc;
0331     op_info = acpi_ps_get_opcode_info(opcode);
0332     if (op_info->class == AML_CLASS_UNKNOWN) {
0333 
0334         /* Unknown opcode */
0335 
0336         return_ACPI_STATUS(AE_TYPE);
0337     }
0338 
0339     /* Perform per-object initialization */
0340 
0341     switch (obj_desc->common.type) {
0342     case ACPI_TYPE_BUFFER:
0343         /*
0344          * Defer evaluation of Buffer term_arg operand
0345          */
0346         obj_desc->buffer.node =
0347             ACPI_CAST_PTR(struct acpi_namespace_node,
0348                   walk_state->operands[0]);
0349         obj_desc->buffer.aml_start = op->named.data;
0350         obj_desc->buffer.aml_length = op->named.length;
0351         break;
0352 
0353     case ACPI_TYPE_PACKAGE:
0354         /*
0355          * Defer evaluation of Package term_arg operand and all
0356          * package elements. (01/2017): We defer the element
0357          * resolution to allow forward references from the package
0358          * in order to provide compatibility with other ACPI
0359          * implementations.
0360          */
0361         obj_desc->package.node =
0362             ACPI_CAST_PTR(struct acpi_namespace_node,
0363                   walk_state->operands[0]);
0364 
0365         if (!op->named.data) {
0366             return_ACPI_STATUS(AE_OK);
0367         }
0368 
0369         obj_desc->package.aml_start = op->named.data;
0370         obj_desc->package.aml_length = op->named.length;
0371         break;
0372 
0373     case ACPI_TYPE_INTEGER:
0374 
0375         switch (op_info->type) {
0376         case AML_TYPE_CONSTANT:
0377             /*
0378              * Resolve AML Constants here - AND ONLY HERE!
0379              * All constants are integers.
0380              * We mark the integer with a flag that indicates that it started
0381              * life as a constant -- so that stores to constants will perform
0382              * as expected (noop). zero_op is used as a placeholder for optional
0383              * target operands.
0384              */
0385             obj_desc->common.flags = AOPOBJ_AML_CONSTANT;
0386 
0387             switch (opcode) {
0388             case AML_ZERO_OP:
0389 
0390                 obj_desc->integer.value = 0;
0391                 break;
0392 
0393             case AML_ONE_OP:
0394 
0395                 obj_desc->integer.value = 1;
0396                 break;
0397 
0398             case AML_ONES_OP:
0399 
0400                 obj_desc->integer.value = ACPI_UINT64_MAX;
0401 
0402                 /* Truncate value if we are executing from a 32-bit ACPI table */
0403 
0404                 (void)acpi_ex_truncate_for32bit_table(obj_desc);
0405                 break;
0406 
0407             case AML_REVISION_OP:
0408 
0409                 obj_desc->integer.value = ACPI_CA_VERSION;
0410                 break;
0411 
0412             default:
0413 
0414                 ACPI_ERROR((AE_INFO,
0415                         "Unknown constant opcode 0x%X",
0416                         opcode));
0417                 status = AE_AML_OPERAND_TYPE;
0418                 break;
0419             }
0420             break;
0421 
0422         case AML_TYPE_LITERAL:
0423 
0424             obj_desc->integer.value = op->common.value.integer;
0425 
0426             if (acpi_ex_truncate_for32bit_table(obj_desc)) {
0427 
0428                 /* Warn if we found a 64-bit constant in a 32-bit table */
0429 
0430                 ACPI_WARNING((AE_INFO,
0431                           "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X",
0432                           ACPI_FORMAT_UINT64(op->common.
0433                                  value.integer),
0434                           (u32)obj_desc->integer.value));
0435             }
0436             break;
0437 
0438         default:
0439 
0440             ACPI_ERROR((AE_INFO, "Unknown Integer type 0x%X",
0441                     op_info->type));
0442             status = AE_AML_OPERAND_TYPE;
0443             break;
0444         }
0445         break;
0446 
0447     case ACPI_TYPE_STRING:
0448 
0449         obj_desc->string.pointer = op->common.value.string;
0450         obj_desc->string.length = (u32)strlen(op->common.value.string);
0451 
0452         /*
0453          * The string is contained in the ACPI table, don't ever try
0454          * to delete it
0455          */
0456         obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
0457         break;
0458 
0459     case ACPI_TYPE_METHOD:
0460         break;
0461 
0462     case ACPI_TYPE_LOCAL_REFERENCE:
0463 
0464         switch (op_info->type) {
0465         case AML_TYPE_LOCAL_VARIABLE:
0466 
0467             /* Local ID (0-7) is (AML opcode - base AML_FIRST_LOCAL_OP) */
0468 
0469             obj_desc->reference.value =
0470                 ((u32)opcode) - AML_FIRST_LOCAL_OP;
0471             obj_desc->reference.class = ACPI_REFCLASS_LOCAL;
0472 
0473             status =
0474                 acpi_ds_method_data_get_node(ACPI_REFCLASS_LOCAL,
0475                              obj_desc->reference.
0476                              value, walk_state,
0477                              ACPI_CAST_INDIRECT_PTR
0478                              (struct
0479                               acpi_namespace_node,
0480                               &obj_desc->reference.
0481                               object));
0482             break;
0483 
0484         case AML_TYPE_METHOD_ARGUMENT:
0485 
0486             /* Arg ID (0-6) is (AML opcode - base AML_FIRST_ARG_OP) */
0487 
0488             obj_desc->reference.value =
0489                 ((u32)opcode) - AML_FIRST_ARG_OP;
0490             obj_desc->reference.class = ACPI_REFCLASS_ARG;
0491 
0492             status = acpi_ds_method_data_get_node(ACPI_REFCLASS_ARG,
0493                                   obj_desc->
0494                                   reference.value,
0495                                   walk_state,
0496                                   ACPI_CAST_INDIRECT_PTR
0497                                   (struct
0498                                    acpi_namespace_node,
0499                                    &obj_desc->
0500                                    reference.
0501                                    object));
0502             break;
0503 
0504         default:    /* Object name or Debug object */
0505 
0506             switch (op->common.aml_opcode) {
0507             case AML_INT_NAMEPATH_OP:
0508 
0509                 /* Node was saved in Op */
0510 
0511                 obj_desc->reference.node = op->common.node;
0512                 obj_desc->reference.class = ACPI_REFCLASS_NAME;
0513                 if (op->common.node) {
0514                     obj_desc->reference.object =
0515                         op->common.node->object;
0516                 }
0517                 break;
0518 
0519             case AML_DEBUG_OP:
0520 
0521                 obj_desc->reference.class = ACPI_REFCLASS_DEBUG;
0522                 break;
0523 
0524             default:
0525 
0526                 ACPI_ERROR((AE_INFO,
0527                         "Unimplemented reference type for AML opcode: 0x%4.4X",
0528                         opcode));
0529                 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
0530             }
0531             break;
0532         }
0533         break;
0534 
0535     default:
0536 
0537         ACPI_ERROR((AE_INFO, "Unimplemented data type: 0x%X",
0538                 obj_desc->common.type));
0539 
0540         status = AE_AML_OPERAND_TYPE;
0541         break;
0542     }
0543 
0544     return_ACPI_STATUS(status);
0545 }