linux/drivers/acpi/acpica/pstree.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2/******************************************************************************
   3 *
   4 * Module Name: pstree - Parser op tree manipulation/traversal/search
   5 *
   6 * Copyright (C) 2000 - 2021, Intel Corp.
   7 *
   8 *****************************************************************************/
   9
  10#include <acpi/acpi.h>
  11#include "accommon.h"
  12#include "acparser.h"
  13#include "amlcode.h"
  14#include "acconvert.h"
  15
  16#define _COMPONENT          ACPI_PARSER
  17ACPI_MODULE_NAME("pstree")
  18
  19/* Local prototypes */
  20#ifdef ACPI_OBSOLETE_FUNCTIONS
  21union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op);
  22#endif
  23
  24/*******************************************************************************
  25 *
  26 * FUNCTION:    acpi_ps_get_arg
  27 *
  28 * PARAMETERS:  op              - Get an argument for this op
  29 *              argn            - Nth argument to get
  30 *
  31 * RETURN:      The argument (as an Op object). NULL if argument does not exist
  32 *
  33 * DESCRIPTION: Get the specified op's argument.
  34 *
  35 ******************************************************************************/
  36
  37union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn)
  38{
  39        union acpi_parse_object *arg = NULL;
  40        const struct acpi_opcode_info *op_info;
  41
  42        ACPI_FUNCTION_ENTRY();
  43
  44/*
  45        if (Op->Common.aml_opcode == AML_INT_CONNECTION_OP)
  46        {
  47                return (Op->Common.Value.Arg);
  48        }
  49*/
  50        /* Get the info structure for this opcode */
  51
  52        op_info = acpi_ps_get_opcode_info(op->common.aml_opcode);
  53        if (op_info->class == AML_CLASS_UNKNOWN) {
  54
  55                /* Invalid opcode or ASCII character */
  56
  57                return (NULL);
  58        }
  59
  60        /* Check if this opcode requires argument sub-objects */
  61
  62        if (!(op_info->flags & AML_HAS_ARGS)) {
  63
  64                /* Has no linked argument objects */
  65
  66                return (NULL);
  67        }
  68
  69        /* Get the requested argument object */
  70
  71        arg = op->common.value.arg;
  72        while (arg && argn) {
  73                argn--;
  74                arg = arg->common.next;
  75        }
  76
  77        return (arg);
  78}
  79
  80/*******************************************************************************
  81 *
  82 * FUNCTION:    acpi_ps_append_arg
  83 *
  84 * PARAMETERS:  op              - Append an argument to this Op.
  85 *              arg             - Argument Op to append
  86 *
  87 * RETURN:      None.
  88 *
  89 * DESCRIPTION: Append an argument to an op's argument list (a NULL arg is OK)
  90 *
  91 ******************************************************************************/
  92
  93void
  94acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg)
  95{
  96        union acpi_parse_object *prev_arg;
  97        const struct acpi_opcode_info *op_info;
  98
  99        ACPI_FUNCTION_TRACE(ps_append_arg);
 100
 101        if (!op) {
 102                return_VOID;
 103        }
 104
 105        /* Get the info structure for this opcode */
 106
 107        op_info = acpi_ps_get_opcode_info(op->common.aml_opcode);
 108        if (op_info->class == AML_CLASS_UNKNOWN) {
 109
 110                /* Invalid opcode */
 111
 112                ACPI_ERROR((AE_INFO, "Invalid AML Opcode: 0x%2.2X",
 113                            op->common.aml_opcode));
 114                return_VOID;
 115        }
 116
 117        /* Check if this opcode requires argument sub-objects */
 118
 119        if (!(op_info->flags & AML_HAS_ARGS)) {
 120
 121                /* Has no linked argument objects */
 122
 123                return_VOID;
 124        }
 125
 126        /* Append the argument to the linked argument list */
 127
 128        if (op->common.value.arg) {
 129
 130                /* Append to existing argument list */
 131
 132                prev_arg = op->common.value.arg;
 133                while (prev_arg->common.next) {
 134                        prev_arg = prev_arg->common.next;
 135                }
 136                prev_arg->common.next = arg;
 137        } else {
 138                /* No argument list, this will be the first argument */
 139
 140                op->common.value.arg = arg;
 141        }
 142
 143        /* Set the parent in this arg and any args linked after it */
 144
 145        while (arg) {
 146                arg->common.parent = op;
 147                arg = arg->common.next;
 148
 149                op->common.arg_list_length++;
 150        }
 151
 152        return_VOID;
 153}
 154
 155/*******************************************************************************
 156 *
 157 * FUNCTION:    acpi_ps_get_depth_next
 158 *
 159 * PARAMETERS:  origin          - Root of subtree to search
 160 *              op              - Last (previous) Op that was found
 161 *
 162 * RETURN:      Next Op found in the search.
 163 *
 164 * DESCRIPTION: Get next op in tree (walking the tree in depth-first order)
 165 *              Return NULL when reaching "origin" or when walking up from root
 166 *
 167 ******************************************************************************/
 168
 169union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin,
 170                                                union acpi_parse_object *op)
 171{
 172        union acpi_parse_object *next = NULL;
 173        union acpi_parse_object *parent;
 174        union acpi_parse_object *arg;
 175
 176        ACPI_FUNCTION_ENTRY();
 177
 178        if (!op) {
 179                return (NULL);
 180        }
 181
 182        /* Look for an argument or child */
 183
 184        next = acpi_ps_get_arg(op, 0);
 185        if (next) {
 186                ASL_CV_LABEL_FILENODE(next);
 187                return (next);
 188        }
 189
 190        /* Look for a sibling */
 191
 192        next = op->common.next;
 193        if (next) {
 194                ASL_CV_LABEL_FILENODE(next);
 195                return (next);
 196        }
 197
 198        /* Look for a sibling of parent */
 199
 200        parent = op->common.parent;
 201
 202        while (parent) {
 203                arg = acpi_ps_get_arg(parent, 0);
 204                while (arg && (arg != origin) && (arg != op)) {
 205
 206                        ASL_CV_LABEL_FILENODE(arg);
 207                        arg = arg->common.next;
 208                }
 209
 210                if (arg == origin) {
 211
 212                        /* Reached parent of origin, end search */
 213
 214                        return (NULL);
 215                }
 216
 217                if (parent->common.next) {
 218
 219                        /* Found sibling of parent */
 220
 221                        ASL_CV_LABEL_FILENODE(parent->common.next);
 222                        return (parent->common.next);
 223                }
 224
 225                op = parent;
 226                parent = parent->common.parent;
 227        }
 228
 229        ASL_CV_LABEL_FILENODE(next);
 230        return (next);
 231}
 232
 233#ifdef ACPI_OBSOLETE_FUNCTIONS
 234/*******************************************************************************
 235 *
 236 * FUNCTION:    acpi_ps_get_child
 237 *
 238 * PARAMETERS:  op              - Get the child of this Op
 239 *
 240 * RETURN:      Child Op, Null if none is found.
 241 *
 242 * DESCRIPTION: Get op's children or NULL if none
 243 *
 244 ******************************************************************************/
 245
 246union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op)
 247{
 248        union acpi_parse_object *child = NULL;
 249
 250        ACPI_FUNCTION_ENTRY();
 251
 252        switch (op->common.aml_opcode) {
 253        case AML_SCOPE_OP:
 254        case AML_ELSE_OP:
 255        case AML_DEVICE_OP:
 256        case AML_THERMAL_ZONE_OP:
 257        case AML_INT_METHODCALL_OP:
 258
 259                child = acpi_ps_get_arg(op, 0);
 260                break;
 261
 262        case AML_BUFFER_OP:
 263        case AML_PACKAGE_OP:
 264        case AML_VARIABLE_PACKAGE_OP:
 265        case AML_METHOD_OP:
 266        case AML_IF_OP:
 267        case AML_WHILE_OP:
 268        case AML_FIELD_OP:
 269
 270                child = acpi_ps_get_arg(op, 1);
 271                break;
 272
 273        case AML_POWER_RESOURCE_OP:
 274        case AML_INDEX_FIELD_OP:
 275
 276                child = acpi_ps_get_arg(op, 2);
 277                break;
 278
 279        case AML_PROCESSOR_OP:
 280        case AML_BANK_FIELD_OP:
 281
 282                child = acpi_ps_get_arg(op, 3);
 283                break;
 284
 285        default:
 286
 287                /* All others have no children */
 288
 289                break;
 290        }
 291
 292        return (child);
 293}
 294#endif
 295